Python'da bir yöntemi parametre olarak nasıl iletirim


191

Bir yöntemi bir yönteme parametre olarak geçirmek mümkün müdür?

self.method2(self.method1)

def method1(self):
    return 'hello world'

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

Yanıtlar:


263

Evet, yazdığınız gibi, sadece yöntemin adını kullanın. Yöntemler / işlevler, Python'daki nesnelerdir, tıpkı her şey gibi, ve değişkenleri nasıl uygulayabileceğinizi aktarabilirsiniz. Aslında, değeri gerçek çağrılabilir kod nesnesi olan bir değişken olarak bir yöntem (veya işlev) hakkında düşünebilirsiniz.

Bilginize, hiçbir callyöntem yok - bence denir __call__, ama açıkça çağırmak zorunda değilsiniz:

def method1():
    return 'hello world'

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

method2(method1)

Eğer method1argümanlarla çağrılmak istersen , işler biraz daha karmaşıklaşır. method2argümanların nasıl aktarılacağı hakkında biraz bilgi ile yazılmalıdır method1ve bu argümanlar için bir yerden değerler alması gerekir. Örneğin, method1bir argüman alması gerekiyorsa:

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

o zaman bunu method2iletilen bir argümanla aramak için yazabilirsiniz :

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

veya kendini hesapladığı iddiasıyla:

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

Bunu, iletilen değerlerin ve hesaplanan değerlerin diğer kombinasyonlarına genişletebilirsiniz.

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)

hatta anahtar kelime bağımsız değişkenleriyle

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

Yazarken method2, hangi argümanların methodToRunalınacağını bilmiyorsanız, genel bir şekilde çağırmak için açma bağımsız değişkenini de kullanabilirsiniz:

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

Bu durumda positional_argumentsbir liste veya grup veya benzer olması gerekir ve keyword_argumentsbir dikte veya benzerdir. İçinde arama yapmadan önce ve method2değiştirebilir (örneğin, belirli bağımsız değişkenler ekleyebilir veya kaldırabilir veya değerleri değiştirebilirsiniz) .positional_argumentskeyword_argumentsmethod1


34

Evet mümkün. Sadece ara:

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

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

1
örnek yoksa ne olur foo?
Lei Yang

1
Sonra sadece foo gerekmez, örneğin: def method1(): pass def method2(method) return method() method2(method1)
Tom

14

Tek başına çalışan bir örnek göstermek için yeniden yazılmış örneğiniz:

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()

6

Evet; fonksiyonlar (ve yöntemler) Python'daki birinci sınıf nesnelerdir. Aşağıdaki işler:

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

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

foo(bar)

Çıktılar:

Running parameter f().
In bar().

Bu tür sorular Python yorumlayıcısını veya daha fazla özellik için IPython kabuğunu kullanarak cevaplamak önemsizdir .


5

Bir sınıfın yöntemini bağımsız değişken olarak geçirmek istiyorsanız, ancak üzerinde çağıracağınız nesneye henüz sahip değilseniz, nesneyi ilk bağımsız değişken olarak (yani "benlik" olarak) argüman).

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)

Bu "Merhaba Dünya" yazdıracak


5

Çok iyi cevaplar ama garip kimse bir lambdafonksiyon kullanarak söz etmedi .
Yani hiçbir argümanınız yoksa, işler oldukça önemsiz hale gelir:

def method1():
    return 'hello world'

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

method2(method1)

Ama diyelim ki içinde bir (veya daha fazla) argüman var method1:

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

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

Sonra sadece çağırabilir method2olarak method2(lambda: method1('world')).

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

Bunu burada bahsedilen diğer cevaplardan çok daha temiz buluyorum.


Bu sözlükteki bir değer olsaydı, bir işlev nesnesini döndürmek yerine bunu nasıl yürütebilirim? Edit: Sadece fark sadece ()benim geri arama, nesnenin sonuna koymak duh.
vaponteblizzard

3

Yöntemler, diğerleri gibi nesnelerdir. Böylece onları aktarabilir, listelerde ve diktelerde saklayabilir, onlarla ne istersen yapabilirsin. Onlarla ilgili özel şey, çağrılabilir nesnelerdir, böylece __call__onları çağırabilirsiniz . __call__Yöntemi bağımsız değişkenlerle veya bağımsız değişkenlerle çağırdığınızda otomatik olarak çağrılır, böylece yalnızca yazmanız gerekir methodToRun().


0

Tam olarak ne istediğinizi değil, ilgili faydalı bir araç da getattr()yöntemin adını parametre olarak kullanmaktır.

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')()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.