从类和该类的实例访问函数

时间:2013-05-30 16:12:39

标签: python python-3.x

有这段代码:

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__函数用于绑定带有函数的对象,但是它如何在内部为类和类实例工作?

1 个答案:

答案 0 :(得分:1)

功能实现为descriptors。引用文档:

  

通常,描述符是具有“绑定行为”的对象属性,其属性访问已被描述符协议中的方法覆盖。这些方法是__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__ documentation中所述,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的工作原理相同,只是未绑定的方法是常规函数。