用户定义的方法与__func__属性

2 投票
1 回答
2349 浏览
提问于 2025-04-21 07:00

有人能解释一下在Python 数据模型参考中关于用户定义函数的这一部分内容吗?

当你从一个类或实例中获取另一个方法对象来创建一个用户定义的方法对象时,它的行为和函数对象是一样的。唯一不同的是,新实例的__func__属性不是原来的方法对象,而是它的__func__属性。

我试着用以下代码来测试这个:

class A(object):
    def foo(self):
        print 'done'
    bar = foo
class B(object): pass

a = A()
b = B()
b.f = a.foo
b.f.__func__  #output:- <function foo at 0x7fe55bed4230>
a.foo.__func__ #output:- <function foo at 0x7fe55bed4230>

这两条语句给我的输出是一样的,但b.f.__func__却没有给我原来的方法对象。我理解得对吗?

1 个回答

3

这段文字讲的是绑定行为。如果一个方法已经被绑定了,但你通过描述符协议来获取它,那么这个方法对象就会像一个函数对象一样工作。不过,这里的__func__属性是被重用的,而不是让新的方法对象指向旧的那个。

你可以通过将foo作为类或实例的属性来触发描述符协议:

>>> class A(object):
...     def foo(self):
...         print 'done'
... 
>>> a = A()
>>> a.foo
<bound method A.foo of <__main__.A object at 0x1007611d0>>
>>> A.foo
<unbound method A.foo>
>>> A.__dict__['foo']
<function foo at 0x10075cc08>
>>> A.bar = A.foo
>>> A.bar
<unbound method A.foo>
>>> A.__dict__['bar']
<unbound method A.foo>
>>> a.bar
<bound method A.foo of <__main__.A object at 0x1007611d0>>
>>> a.bar.__func__
<function foo at 0x10075cc08>

在上面的例子中,我使用了A.__dict__来绕过描述符协议。你可以看到,A.__dict__['foo']是一个函数对象,而A.__dict__['bar']是一个未绑定的方法。但是当你访问A.bara.bar时,你得到的是一个方法对象,它指向原始的函数对象,而不是我们从A.foo获取的方法。

所以你的理解是正确的;b.f是绑定的a.foo方法,因此b.f.__func__会指向与a.foo.__func__相同的对象。

撰写回答