Bagaimana cara melewati metode sebagai parameter dalam Python

191

Apakah mungkin untuk meneruskan metode sebagai parameter ke metode?

self.method2(self.method1)

def method1(self):
    return 'hello world'

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

Jawaban:

263

Ya itu, cukup gunakan nama metode, seperti yang Anda tulis. Metode / fungsi adalah objek dalam Python, sama seperti yang lainnya, dan Anda bisa meneruskannya di sekitar cara Anda melakukan variabel. Bahkan, Anda dapat berpikir tentang metode (atau fungsi) sebagai variabel yang nilainya adalah objek kode yang sebenarnya bisa dipanggil.

FYI, tidak ada callmetode - saya pikir itu disebut __call__, tetapi Anda tidak harus memanggilnya secara eksplisit:

def method1():
    return 'hello world'

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

method2(method1)

Jika Anda ingin method1dipanggil dengan argumen, maka segala sesuatunya menjadi sedikit lebih rumit. method2harus ditulis dengan sedikit informasi tentang cara meneruskan argumen method1, dan perlu mendapatkan nilai untuk argumen tersebut dari suatu tempat. Misalnya, jika method1dianggap mengambil satu argumen:

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

maka Anda bisa menulis method2untuk menyebutnya dengan satu argumen yang diteruskan:

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

atau dengan argumen yang dihitung sendiri:

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

Anda dapat memperluas ini ke kombinasi nilai lain yang diteruskan dan nilai yang dihitung, seperti

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)

atau bahkan dengan argumen kata kunci

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

Jika Anda tidak tahu, saat menulis method2, argumen apa methodToRunyang akan diambil, Anda juga dapat menggunakan argumen unpacking untuk menyebutnya dengan cara umum:

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

Dalam hal ini positional_argumentsperlu daftar atau tuple atau serupa, dan keyword_argumentsmerupakan dict atau serupa. Di method2Anda dapat memodifikasi positional_argumentsdan keyword_arguments(misalnya untuk menambah atau menghapus argumen tertentu atau mengubah nilai) sebelum Anda menelepon method1.

David Z
sumber
34

Ya itu mungkin. Sebut saja:

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

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

sumber
1
bagaimana jika tidak ada contoh foo?
Lei Yang
1
Maka Anda tidak perlu foo, misalnya: def method1(): pass def method2(method) return method() method2(method1)
Tom
14

Ini adalah contoh Anda yang ditulis ulang untuk menunjukkan contoh kerja yang berdiri sendiri:

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
sumber
6

Iya; fungsi (dan metode) adalah objek kelas satu di Python. Karya-karya berikut:

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

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

foo(bar)

Output:

Running parameter f().
In bar().

Pertanyaan-pertanyaan semacam ini sepele untuk dijawab menggunakan interpreter Python atau, untuk lebih banyak fitur, shell IPython .

lt_kije
sumber
5

Jika Anda ingin meneruskan metode kelas sebagai argumen tetapi belum memiliki objek yang akan Anda panggil, Anda bisa meneruskan objek begitu Anda memilikinya sebagai argumen pertama (yaitu "diri" argumen).

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)

Ini akan mencetak "Hello World"

Sisi depan
sumber
5

Banyak jawaban bagus tetapi aneh bahwa tidak ada yang menyebutkan menggunakan lambdafungsi.
Jadi, jika Anda tidak memiliki argumen, semuanya menjadi sangat sepele:

def method1():
    return 'hello world'

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

method2(method1)

Tetapi katakan Anda memiliki satu (atau lebih) argumen di method1:

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

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

Maka Anda bisa memanggil method2sebagai method2(lambda: method1('world')).

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

Saya menemukan ini jauh lebih bersih daripada jawaban lain yang disebutkan di sini.

Scrotch
sumber
Jika ini adalah nilai dalam kamus, bagaimana saya bisa menjalankannya daripada mengembalikan objek fungsi? Sunting: Baru sadar saya bisa meletakkan ()di ujung objek di panggilan balik saya, ya.
vaponteblizzard
3

Metode adalah objek seperti yang lainnya. Jadi Anda bisa menyebarkannya, menyimpannya dalam daftar dan dikte, melakukan apa pun yang Anda suka dengan mereka. Hal khusus tentang mereka adalah benda-benda yang bisa dipanggil sehingga Anda dapat memintanya __call__. __call__dipanggil secara otomatis ketika Anda memanggil metode dengan atau tanpa argumen sehingga Anda hanya perlu menulis methodToRun().

Vasil
sumber
0

Tidak persis seperti yang Anda inginkan, tetapi alat bermanfaat yang terkait adalah getattr(), untuk menggunakan nama metode sebagai parameter.

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
sumber