descriptor(描述符)是python中比较高阶的概念,通过以下示例加深一下对descriptor的理解。
首先看一组比较费解的代码(functions are descriptiors)
def adder(x,y):
return x+y
add23 = adder.__get__(23)
add23(100)
# 123
python通过非数据描述符连接了面向对象和基于函数构建的两个重要特性
那普通函数和类方法函数的不同点是什么呢,类方法的第一个参数存储了对象实例引用,python中通常写作self
。具体如下:
class D(object):
def f(self, x):
return x
d = D()
d.f
# <bound method D.f of <__main__.D object at 0x00000000077EECC0>>
d.f.__self__
# <__main__.D at 0x77eecc0>
d.f.__func__
# <function __main__.D.f>
d.f.__class__
# method
adder.__class__ #文章一开始定义的函数
# function
因此python的funcobject
为了同时支持method
和function
两种调用方式,在获取类属性时候,函数通过实现__get__()
方法来绑定,即: 当函数作为一个方法被一个对象调用的时候,python中所有的函数都是一个返回绑定方法的非数据描述符。有类似如下的结构:
import types
class Function(object):
. . .
def __get__(self, obj, objtype=None):
"Simulate func_descr_get() in Objects/funcobject.c"
if obj is None:
return self
return types.MethodType(self, obj)
# types.MethodType:
# method(function, instance)
# Create a bound instance method object.
所有的函数和方法均为上面定义的Function
的实例,为obj
对象创建一个绑定的方法self
。
说到这里,应该能解释最开始这个费解的示例了。
adder.__get__(23)
返回的是:23这个整数对象的adder方法(描述符把adder这个方法绑定到了23上)
add23.__class__
# method 可以看到不是function而是method
add23.__self__
# 23
python通过描述符统一了函数和方法两种不同调用方式
网友评论