如何在Python中将方法作为参数传递

时间:2009-04-01 18:06:54

标签: python parameter-passing

是否可以将方法作为参数传递给方法?

self.method2(self.method1)

def method1(self):
    return 'hello world'

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

9 个答案:

答案 0 :(得分:206)

是的,只需使用方法的名称,就像你写的那样。方法/函数是Python中的对象,就像其他任何东西一样,你可以将它们传递给你做变量的方式。实际上,您可以将方法(或函数)视为一个变量,其值是实际的可调用代码对象。

仅供参考,没有call方法 - 我认为它被称为__call__,但你不必明确地调用它:

def method1():
    return 'hello world'

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

method2(method1)

如果你想用参数调用method1,那么事情会变得复杂一些。 method2必须写一些关于如何将参数传递给method1的信息,并且需要从某个地方获取这些参数的值。例如,如果method1应该采用一个参数:

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

然后您可以编写method2来调用它,并使用一个传入的参数:

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

或者使用自己计算的参数:

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

您可以将其扩展为传入的其他值组合和计算的值,例如

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)

或甚至使用关键字参数

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

如果您不知道,在编写method2时,methodToRun将采用什么参数,您还可以使用参数解包来以通用方式调用它:

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

在这种情况下,positional_arguments需要是列表或元组或类似名称,而keyword_arguments是dict或类似名称。在method2中,您可以在致电positional_arguments之前修改keyword_argumentsmethod1(例如,添加或删除某些参数或更改值)。

答案 1 :(得分:31)

是的,这是可能的。只需称呼它:

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

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

答案 2 :(得分:12)

以下是您重写的示例,以显示一个独立的工作示例:

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

答案 3 :(得分:5)

是;函数(和方法)是Python中的第一类对象。以下作品:

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

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

foo(bar)

输出:

Running parameter f().
In bar().

使用Python解释器回答这些问题是微不足道的,或者对于更多功能,使用IPython shell。

答案 4 :(得分:2)

方法就像任何其他对象一样。所以你可以传递它们,将它们存储在列表和词典中,随心所欲地做任何事情。关于它们的特殊之处在于它们是可调用对象,因此您可以在它们上调用__call__。当您使用或不使用参数调用方法时会自动调用__call__,因此您只需要编写methodToRun()

答案 5 :(得分:2)

如果你想传递一个类的方法作为一个参数但是还没有你要调用它的对象,你只需将它作为第一个参数传递给它(即" self"参数)。

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)

这将打印" Hello World"

答案 6 :(得分:2)

不是完全想要的,但一个相关的有用工具是getattr(),可以使用方法的名称作为参数。

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

答案 7 :(得分:2)

示例:一个简单的函数调用包装器:

def measure_cpu_time(f, *args):
    t_start = time.process_time()
    ret = f(*args)
    t_end = time.process_time()
    return t_end - t_start, ret

答案 8 :(得分:1)

很多很好的答案,但奇怪的是没有人提到使用lambda函数。
因此,如果没有参数,事情会变得很简单:

def method1():
    return 'hello world'

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

method2(method1)

但是请说您在method1中有一个(或多个)参数:

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

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

然后,您可以简单地将method2作为method2(lambda: method1('world'))来调用。

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

我发现这里的答案比这里提到的其他答案要干净得多。