Python:传递方法作为函数参数时出现属性错误
我本以为在Stack Overflow上能找到这个问题的答案,但我一直没找到;大多数讨论都是关于把函数作为参数传递,而不是把方法作为参数传递给函数。
我现在在用Python 2.7.5,想定义一个这样的函数:
def func(object, method):
object.method()
当这样调用的时候:
some_object_instance = SomeObject()
func(some_object_instance, SomeObject.some_object_method)
使用一个这样定义的类:
class SomeObject:
def some_object_method(self):
# do something
基本上等同于这样做:
some_object_instance.some_object_method()
但是,我总是遇到一个属性错误——大概是这样的:
'SomeObject' has no attribute 'method'
我原以为我可以合法地把方法作为参数传递,并且在上述方式中正确使用它们。那我到底漏掉了什么呢?
2 个回答
因为你传递的是一个没有绑定的函数,所以你需要这样调用它:
method(object)
或者更好的方法是把函数的名字作为字符串传进去,然后用 getattr
来获取它:
getattr(object, method)()
方法调用并不是这样工作的。foo.bar
这种写法是用来查找 foo
对象上名为 bar
的方法。如果你已经有这个方法了,那就直接调用它就行:
def func(object, method):
method(object)
func(some_object_instance, SomeObject.some_object_method)
SomeObject.some_object_method
被称为“未绑定方法”:它是一个没有绑定 self
的方法对象,所以你需要手动把 self
传给它。
用一个具体的例子可能会更好理解:
>>> s = 'ABC'
>>> s_lower = s.lower # bound method
>>> s_lower()
'abc'
>>> str_lower = str.lower # unbound method
>>> str_lower(s)
'abc'
相比之下,some_object_instance.some_object_method
是一个“绑定方法”,你可以直接调用它,而 some_object_instance
已经作为 self
参数绑定进来了:
def func2(method):
method()
func2(some_object_instance.some_object_method)
未绑定方法在教程中没有详细解释;它们在关于 绑定方法 的部分有提到。所以你需要去参考手册查找文档(在 [标准类型层次结构] (https://docs.python.org/2/reference/datamodel.html#the-standard-type-hierarchy),在“用户定义的方法”小节里),这对初学者来说可能有点难。
就我个人而言,直到我了解了它的底层工作原理,我才真正明白这一点。大约一年前,我写了一篇博客文章 方法是如何工作的,试图向别人解释这个问题(不过是用 Python 3.x 的术语,稍微有些不同);这可能会对你有帮助。要想真正理解,你需要读一读 描述符 HOWTO,这可能需要多读几遍,并在交互式解释器中多尝试几次,才能真正明白,但希望在你到达那个阶段之前,你能理解方法背后的基本概念。