Wie übergebe ich eine Methode als Parameter in Python?

188

Ist es möglich, eine Methode als Parameter an eine Methode zu übergeben?

self.method2(self.method1)

def method1(self):
    return 'hello world'

def method2(self, methodToRun):
    result = methodToRun.call()
    return result
Dan
quelle

Antworten:

261

Ja, verwenden Sie einfach den Namen der Methode, wie Sie geschrieben haben. Methoden / Funktionen sind wie alles andere Objekte in Python, und Sie können sie so übergeben, wie Sie Variablen ausführen. Tatsächlich können Sie sich eine Methode (oder Funktion) als eine Variable vorstellen, deren Wert das tatsächlich aufrufbare Codeobjekt ist.

Zu Ihrer Information, es gibt keine callMethode - ich denke, sie heißt __call__, aber Sie müssen sie nicht explizit aufrufen:

def method1():
    return 'hello world'

def method2(methodToRun):
    result = methodToRun()
    return result

method2(method1)

Wenn Sie method1mit Argumenten aufgerufen werden wollten , werden die Dinge etwas komplizierter. method2muss mit ein paar Informationen darüber geschrieben werden, wie Argumente übergeben werden sollen method1, und es müssen Werte für diese Argumente von irgendwoher abgerufen werden. Zum Beispiel, wenn method1ein Argument angenommen werden soll:

def method1(spam):
    return 'hello ' + str(spam)

dann könnten Sie schreiben method2, um es mit einem Argument aufzurufen, das übergeben wird:

def method2(methodToRun, spam_value):
    return methodToRun(spam_value)

oder mit einem Argument, dass es sich selbst berechnet:

def method2(methodToRun):
    spam_value = compute_some_value()
    return methodToRun(spam_value)

Sie können dies auf andere Kombinationen von übergebenen Werten und berechneten Werten erweitern, z

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)

oder sogar mit Schlüsselwortargumenten

def method2(methodToRun, ham_value):
    spam_value = compute_some_value()
    return methodToRun(spam_value, ham=ham_value)

Wenn Sie beim Schreiben nicht wissen, method2welche Argumente verwendet werden sollen methodToRun, können Sie das Entpacken von Argumenten auch verwenden, um es generisch aufzurufen:

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'})

In diesem Fall positional_argumentsmuss es sich um eine Liste oder ein Tupel oder ähnliches handeln und keyword_argumentsist ein Diktat oder ähnliches. In method2können Sie vor dem Aufruf ändern positional_argumentsund keyword_arguments(z. B. um bestimmte Argumente hinzuzufügen oder zu entfernen oder die Werte zu ändern) method1.

David Z.
quelle
34

Ja, es ist möglich. Nennen Sie es einfach:

class Foo(object):
    def method1(self):
        pass
    def method2(self, method):
        return method()

foo = Foo()
foo.method2(foo.method1)

quelle
1
Was ist, wenn es keine Instanz gibt foo?
Lei Yang
1
Dann brauchen Sie einfach kein Foo, zB: def method1(): pass def method2(method) return method() method2(method1)
Tom
14

Hier ist Ihr Beispiel, das neu geschrieben wurde, um ein eigenständiges Arbeitsbeispiel zu zeigen:

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()
Trent
quelle
6

Ja; Funktionen (und Methoden) sind erstklassige Objekte in Python. Folgendes funktioniert:

def foo(f):
    print "Running parameter f()."
    f()

def bar():
    print "In bar()."

foo(bar)

Ausgänge:

Running parameter f().
In bar().

Diese Art von Fragen ist mit dem Python-Interpreter oder für weitere Funktionen der IPython- Shell trivial zu beantworten .

lt_kije
quelle
5

Wenn Sie eine Methode einer Klasse als Argument übergeben möchten, aber noch nicht das Objekt haben, für das Sie es aufrufen möchten, können Sie das Objekt einfach übergeben, sobald Sie es als erstes Argument haben (dh das "Selbst"). Streit).

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)

Dies wird "Hallo Welt" drucken

Vorderseite
quelle
4

Viele gute Antworten, aber seltsam, dass niemand die Verwendung einer lambdaFunktion erwähnt hat.
Wenn Sie also keine Argumente haben, werden die Dinge ziemlich trivial:

def method1():
    return 'hello world'

def method2(methodToRun):
    result = methodToRun()
    return result

method2(method1)

Angenommen, Sie haben ein (oder mehrere) Argumente in method1:

def method1(param):
    return 'hello ' + str(param)

def method2(methodToRun):
    result = methodToRun()
    return result

Dann können Sie einfach method2als aufrufen method2(lambda: method1('world')).

method2(lambda: method1('world'))
>>> hello world
method2(lambda: method1('reader'))
>>> hello reader

Ich finde das viel sauberer als die anderen hier erwähnten Antworten.

Scrotch
quelle
Wenn dies ein Wert in einem Wörterbuch wäre, wie könnte ich ihn ausführen, anstatt ein Funktionsobjekt zurückzugeben? Bearbeiten: Ich habe gerade festgestellt, dass ich ()in meinem Rückruf einfach das Ende des Objekts einfügen kann, duh.
vaponteblizzard
3

Methoden sind Objekte wie alle anderen. So können Sie sie weitergeben, in Listen und Diktaten speichern und mit ihnen machen, was Sie wollen. Das Besondere an ihnen ist, dass es sich um aufrufbare Objekte handelt, die Sie aufrufen __call__können. __call__wird automatisch aufgerufen, wenn Sie die Methode mit oder ohne Argumente aufrufen, sodass Sie nur schreiben müssen methodToRun().

Vasil
quelle
0

Nicht genau das, was Sie wollen, aber ein verwandtes nützliches Werkzeug ist es getattr(), den Namen der Methode als Parameter zu verwenden.

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')()
Dersu Giritlioğlu
quelle