Comment puis-je passer une méthode en tant que paramètre en Python
-
22-08-2019 - |
Question
Est-il possible d'adopter une méthode en tant que paramètre à une méthode?
self.method2(self.method1)
def method1(self):
return 'hello world'
def method2(self, methodToRun):
result = methodToRun.call()
return result
La solution
Oui il est, il suffit d'utiliser le nom de la méthode, comme vous l'avez écrit. Méthodes / fonctions sont des objets en Python, comme tout le reste, et vous pouvez les passer autour de la façon dont vous faites des variables. En fait, vous pouvez penser à une méthode (ou la fonction) comme une variable dont la valeur est l'objet de code appelable réel.
Pour votre information, il n'y a pas de méthode de call
- Je pense qu'il est appelé __call__
, mais vous ne devez pas l'invoquer explicitement:
def method1():
return 'hello world'
def method2(methodToRun):
result = methodToRun()
return result
method2(method1)
Si vous voulez method1
être appelé avec des arguments, alors les choses deviennent un peu plus compliqué. method2
doit être écrit avec un peu d'informations sur la façon de passer des arguments à method1
, et il a besoin pour obtenir des valeurs pour les arguments de quelque part. Par exemple, si method1
est censé prendre un argument:
def method1(spam):
return 'hello ' + str(spam)
vous pouvez écrire method2
appeler avec un argument qui est passé dans:
def method2(methodToRun, spam_value):
return methodToRun(spam_value)
ou avec un argument selon lequel il se calcule:
def method2(methodToRun):
spam_value = compute_some_value()
return methodToRun(spam_value)
Vous pouvez étendre cela à d'autres combinaisons de valeurs passées et les valeurs calculées, comme
def method1(spam, ham):
return 'hello ' + str(spam) + ' and ' + str(ham)
def method2(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(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
va prendre, vous pouvez également utiliser l'argument de déballer l'appeler d'une manière générique:
def method1(spam, ham):
return 'hello ' + str(spam) + ' and ' + str(ham)
def method2(methodToRun, positional_arguments, keyword_arguments):
return methodToRun(*positional_arguments, **keyword_arguments)
method2(method1, ['spam'], {'ham': 'ham'})
Dans ce cas positional_arguments
doit être une liste ou tuple ou similaire, et keyword_arguments
est un dict ou similaire. En method2
vous pouvez modifier positional_arguments
et keyword_arguments
(par exemple pour ajouter ou supprimer certains arguments ou modifier les valeurs) avant d'appeler method1
.
Autres conseils
Oui, il est possible. Il suffit de l'appeler:
class Foo(object):
def method1(self):
pass
def method2(self, method):
return method()
foo = Foo()
foo.method2(foo.method1)
Voici votre exemple re-écrit pour montrer un exemple de travail autonome:
class Test:
def method1(self):
return 'hello world'
def method2(self, methodToRun):
result = methodToRun()
return result
def method3(self):
return self.method2(self.method1)
test = Test()
print test.method3()
Oui; (fonctions et méthodes) sont les premiers objets de classe en python. Les travaux suivants:
def foo(f):
print "Running parameter f()."
f()
def bar():
print "In bar()."
foo(bar)
Sorties:
Running parameter f().
In bar().
Ces sortes de questions sont très simples à répondre en utilisant l'interpréteur Python ou, pour plus de fonctionnalités, IPython .
Si vous voulez passer une méthode d'une classe comme un argument, mais n'ont pas encore l'objet sur lequel vous allez l'appeler, vous pouvez tout simplement passer l'objet une fois que vous l'avez comme premier argument (la argument "auto").
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)
imprimera "Bonjour tout le monde"
Les méthodes sont des objets comme les autres. Ainsi, vous pouvez les faire passer, de les stocker dans des listes et dicts, faites tout ce que vous aimez avec eux. La chose particularité est qu'ils sont des objets appelables de sorte que vous pouvez invoquer __call__
sur eux. __call__
est appelée automatiquement lorsque vous invoquez la méthode avec ou sans arguments que vous avez juste besoin d'écrire methodToRun()
.
Beaucoup de bonnes réponses, mais étrange que personne ne l'a mentionné en utilisant une fonction de lambda
.
Donc, si vous avez pas d'arguments, les choses deviennent assez trivial:
def method1():
return 'hello world'
def method2(methodToRun):
result = methodToRun()
return result
method2(method1)
Mais que vous avez un des arguments en method1
(ou plus):
def method1(spam):
return 'hello ' + str(spam)
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.