3

有这个代码:

class B:
    def f(self):
        pass

print(B.f) # <function B.f at 0xb711977c>
print(B().f) # <bound method B.f of <__main__.B object at 0xb71774cc>>

解释器如何知道当f从类对象访问函数时返回普通函数,但是当从类实例访问该函数时返回绑定方法?我读到有一个__get__函数用于将对象与函数绑定,但是它如何在内部用于类和类实例?

4

1 回答 1

1

函数被实现为描述符。引用文档:

通常,描述符是具有“绑定行为”的对象属性,其属性访问已被描述符协议中的方法覆盖。这些方法是__get__()__set__()__delete__()。如果为对象定义了这些方法中的任何一个,则称其为描述符。

这个想法是该__get__方法允许识别属性是如何获取的。考虑这个简单的例子:

>>> class Descriptor(object):
...     def __get__(self, obj, type=None):
...         print '__get__(%r, %r)' % (obj, type)
...
>>> class A(object):
...     desc = Descriptor()
...
>>> A.desc
__get__(None, <class '__main__.A'>)
>>> A().desc
__get__(<__main__.A object at 0x020F5B50>, <class '__main__.A'>)

如您所见,并且如__get__文档中所述,该obj参数允许通过类或实例区分属性访问。Python 的内部可以使用相同的机制在访问函数属性时返回绑定或未绑定的方法。

在实践中:

>>> class A:
...     def f(self):
...             pass
...
>>> A.f.__get__(None, A)
<unbound method A.f>
>>> A.f.__get__(A(), A)
<bound method A.f of <__main__.A instance at 0x022082D8>>

这都是 Python 2.x 的示例,但据我所知,Python 3.x 的工作方式相同,只是未绑定的方法是常规函数。

于 2013-05-30T16:45:42.773 回答