Est-il possible de passer une méthode comme paramètre à une méthode?
self.method2(self.method1)
def method1(self):
return 'hello world'
def method2(self, methodToRun):
result = methodToRun.call()
return result
Réponses:
Oui, il suffit d'utiliser le nom de la méthode, comme vous l'avez écrit. Les méthodes et les fonctions sont des objets en Python, comme toute autre chose, et vous pouvez les transmettre comme vous le faites pour les variables. En fait, vous pouvez considérer une méthode (ou une fonction) comme une variable dont la valeur est l'objet de code appelable réel.
Puisque vous avez posé des questions sur les méthodes, j'utilise des méthodes dans les exemples suivants, mais notez que tout ce qui suit s'applique de manière identique aux fonctions (sauf sans le self
paramètre).
Pour appeler une méthode ou une fonction passée, vous utilisez simplement le nom auquel elle est liée de la même manière que vous utiliseriez le nom régulier de la méthode (ou de la fonction):
def method1(self):
return 'hello world'
def method2(self, methodToRun):
result = methodToRun()
return result
obj.method2(obj.method1)
Remarque: je crois qu'une __call__()
méthode existe, c'est-à-dire que vous pourriez techniquement le faire methodToRun.__call__()
, mais vous ne devriez probablement jamais le faire explicitement. __call__()
est destiné à être implémenté, pas à être appelé à partir de votre propre code.
Si vous vouliez method1
être appelé avec des arguments, les choses se compliquent un peu. method2
doit être écrit avec un peu d'informations sur la façon de passer des arguments à method1
, et il doit obtenir des valeurs pour ces arguments de quelque part. Par exemple, si method1
est censé prendre un argument:
def method1(self, spam):
return 'hello ' + str(spam)
alors vous pouvez écrire method2
pour l'appeler avec un argument qui est passé:
def method2(self, methodToRun, spam_value):
return methodToRun(spam_value)
ou avec un argument qu'il calcule lui-même:
def method2(self, methodToRun):
spam_value = compute_some_value()
return methodToRun(spam_value)
Vous pouvez étendre cela à d'autres combinaisons de valeurs transmises et de valeurs calculées, comme
def method1(self, spam, ham):
return 'hello ' + str(spam) + ' and ' + str(ham)
def method2(self, methodToRun, ham_value):
spam_value = compute_some_value()
return methodToRun(spam_value, ham_value)
ou même avec des arguments de mots clés
def method2(self, methodToRun, ham_value):
spam_value = compute_some_value()
return methodToRun(spam_value, ham=ham_value)
Si vous ne savez pas, lors de l'écriture method2
, quels arguments methodToRun
vont prendre, vous pouvez également utiliser la décompression d'arguments pour l'appeler de manière générique:
def method1(self, spam, ham):
return 'hello ' + str(spam) + ' and ' + str(ham)
def method2(self, methodToRun, positional_arguments, keyword_arguments):
return methodToRun(*positional_arguments, **keyword_arguments)
obj.method2(obj.method1, ['spam'], {'ham': 'ham'})
Dans ce cas, il positional_arguments
doit s'agir d'une liste ou d'un tuple ou similaire, et keyword_arguments
est un dict ou similaire. Dans method2
vous pouvez modifier positional_arguments
et keyword_arguments
(par exemple pour ajouter ou supprimer certains arguments ou changer les valeurs) avant d'appeler method1
.
func(obj.method)
. Vous avez expliqué comment passer une fonction en tant que paramètre par exemple func(other_func)
, mais en vous référant aux fonctions en tant que méthodes. J'ai trouvé cela très déroutant.
Oui c'est possible. Appelez-le simplement:
class Foo(object):
def method1(self):
pass
def method2(self, method):
return method()
foo = Foo()
foo.method2(foo.method1)
foo
?
def method1(): pass def method2(method) return method() method2(method1)
Oui; les fonctions (et méthodes) sont des objets de première classe en Python. Les travaux suivants:
def foo(f):
print "Running parameter f()."
f()
def bar():
print "In bar()."
foo(bar)
Les sorties:
Running parameter f().
In bar().
Il est facile de répondre à ces types de questions en utilisant l'interpréteur Python ou, pour plus de fonctionnalités, le shell IPython .
Si vous voulez passer une méthode d'une classe comme argument mais que vous n'avez pas encore l'objet sur lequel vous allez l'appeler, vous pouvez simplement passer l'objet une fois que vous l'avez comme premier argument (ie le "self" argument).
class FooBar:
def __init__(self, prefix):
self.prefix = prefix
def foo(self, name):
print "%s %s" % (self.prefix, name)
def bar(some_method):
foobar = FooBar("Hello")
some_method(foobar, "World")
bar(FooBar.foo)
Cela imprimera "Hello World"
Beaucoup de bonnes réponses mais étranges que personne n'ait mentionnées en utilisant une lambda
fonction.
Donc, si vous n'avez pas d'arguments, les choses deviennent assez triviales:
def method1():
return 'hello world'
def method2(methodToRun):
result = methodToRun()
return result
method2(method1)
Mais disons que vous avez un (ou plusieurs) arguments dans method1
:
def method1(param):
return 'hello ' + str(param)
def method2(methodToRun):
result = methodToRun()
return result
Ensuite, vous pouvez simplement invoquer method2
comme method2(lambda: method1('world'))
.
method2(lambda: method1('world'))
>>> hello world
method2(lambda: method1('reader'))
>>> hello reader
Je trouve cela beaucoup plus propre que les autres réponses mentionnées ici.
()
à la fin de l'objet dans mon appel de retour, duh.
Les méthodes sont des objets comme les autres. Vous pouvez donc les faire circuler, les stocker dans des listes et des dictionnaires, en faire ce que vous voulez. La particularité d'eux est qu'ils sont des objets appelables, vous pouvez donc les invoquer __call__
. __call__
est appelé automatiquement lorsque vous appelez la méthode avec ou sans arguments, il vous suffit donc d'écrire methodToRun()
.
Pas exactement ce que vous voulez, mais un outil utile connexe est getattr()
d'utiliser le nom de la méthode comme paramètre.
class MyClass:
def __init__(self):
pass
def MyMethod(self):
print("Method ran")
# Create an object
object = MyClass()
# Get all the methods of a class
method_list = [func for func in dir(MyClass) if callable(getattr(MyClass, func))]
# You can use any of the methods in method_list
# "MyMethod" is the one we want to use right now
# This is the same as running "object.MyMethod()"
getattr(object,'MyMethod')()
method
avecfunction
.def method1(spam):
est une définition de fonction, pas une définition de méthode.