Python:传递方法作为函数参数时出现属性错误

1 投票
2 回答
1228 浏览
提问于 2025-04-18 18:41

我本以为在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 个回答

0

因为你传递的是一个没有绑定的函数,所以你需要这样调用它:

method(object)

或者更好的方法是把函数的名字作为字符串传进去,然后用 getattr 来获取它:

getattr(object, method)()
2

方法调用并不是这样工作的。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,这可能需要多读几遍,并在交互式解释器中多尝试几次,才能真正明白,但希望在你到达那个阶段之前,你能理解方法背后的基本概念。

撰写回答