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

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

self.method2(self.method1)


def method1(self):
return 'hello world'


def method2(self, methodToRun):
result = methodToRun.call()
return result
274670 次浏览

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

既然你问了方法,我在下面的例子中使用了方法,但请注意,下面的所有内容都同样适用于函数(除了没有self参数)。

要调用传递的方法或函数,你只需要使用它绑定的名称,就像使用方法(或函数)的常规名称一样:

def method1(self):
return 'hello world'


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


obj.method2(obj.method1)

注意:我相信__call__()方法确实存在,即你可以技术上做methodToRun.__call__(),但你可能永远不应该显式这样做。__call__()是要实现的,而不是要从你自己的代码中调用。

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

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

那么你可以编写method2来调用它,并传入一个参数:

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

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

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

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

def method1(self, spam, ham):
return 'hello ' + str(spam) + ' and ' + str(ham)


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

甚至可以使用关键字参数

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

如果你在编写method2时不知道methodToRun将接受哪些参数,你也可以使用参数解包以通用的方式调用它:

def method1(self, spam, ham):
return 'hello ' + str(spam) + ' and ' + str(ham)


def method2(self, methodToRun, positional_arguments, keyword_arguments):
return methodToRun(*positional_arguments, **keyword_arguments)


obj.method2(obj.method1, ['spam'], {'ham': 'ham'})

在这种情况下,positional_arguments需要是一个列表或元组或类似类型,而keyword_arguments是一个字典或类似类型。在method2中,您可以在调用method1之前修改positional_argumentskeyword_arguments(例如,添加或删除某些参数或更改值)。

是的,这是可能的。就叫它:

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


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

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

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


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


foo(bar)

输出:

Running parameter f().
In bar().

使用Python解释器或IPython shell来回答这类问题是微不足道的。

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

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

方法和其他对象一样都是对象。所以你可以传递它们,把它们存储在列表和字典中,做任何你喜欢的事情。它们的特殊之处在于它们是可调用对象,所以你可以对它们调用__call____call__会在你调用方法时自动调用,所以你只需要写methodToRun()

如果你想传递一个类的方法作为参数,但还没有你要调用它的对象,你可以简单地传递对象,一旦你有它作为第一个参数(即“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

使用lambda函数。< br > 所以如果你没有参数,事情变得非常琐碎:

def method1():
return 'hello world'


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


method2(method1)

但假设你在method1中有一个(或多个)参数:

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


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

然后你可以简单地调用method2作为method2(lambda: method1('world'))。< br >

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

我发现这个答案比这里提到的其他答案清晰得多。

不是你想要的,但是一个相关的有用的工具是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')()

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

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