dict.fromkeys
的函数描述符为什么与其他普通函数不同。
首先,您无法像这样访问__get__
:dict.fromkeys.__get__
必须从__dict__
获取。 (dict.__dict__['fromkeys'].__get__
)
然后它不像其他任何函数那样工作,因为它只会让自己绑定到dict
上。
这按我预期的效果很好:
class Thing:
def __init__(self):
self.v = 5
def test(self):
print self.v
class OtherThing:
def __init__(self):
self.v = 6
print Thing.test
Thing.test.__get__(OtherThing())
但这会执行一些意外操作:
#unbound method fromkeys
func = dict.__dict__["fromkeys"]
但是它的描述不同于普通的未绑定函数,看起来像:<method 'fromkeys' of 'dict' objects>
而不是:<unbound method dict.fromkeys>
这就是我的
这按预期工作:
func.__get__({})([1,2,3])
但是您不能将其绑定到其他我理解的东西上,这是行不通的,但这通常不会阻止我们:
func.__get__([])([1,2,3])
此操作因函数描述符中的类型错误而失败...:
descriptor 'fromkeys' for type 'dict' doesn't apply to type 'list'
为什么python会这样区分内置类型函数和普通函数?我们也可以这样做吗?我们可以制作一个仅绑定到其所属类型的函数吗?
答案 0 :(得分:1)
class_or_type.descriptor
总是调用descriptor.__get__(None, class_or_type)
,这就是为什么您无法从内置绑定方法对象获得__get__
的原因。在Python 2函数上为method
生成的{unbound} __get__
类型显式实现了__get__
,因为Python方法更加灵活。因此builtin.descriptor
和class.descriptor
都调用.__get__()
,但是返回的对象类型不同,对于Python方法,对象类型代理具有属性访问权限:
另一方面,通过__dict__
访问属性,从不调用__get__
,因此class_or_type.__dict__['fromkeys']
为您提供了原始描述符对象。
在幕后,像dict
这样的类型(包括其方法)是用C代码实现的,不是用Python代码实现的,而C对类型的挑剔要强得多。您永远无法使用旨在与带有列表的dict
对象的内部实现细节一起使用的函数,那为什么要麻烦呢?
这就是全部内容;内置类型的方法与用Python实现的函数/方法不一样,因此,尽管它们大多工作相同,但它们不能用于动态类型,以及描述符如何工作的实现反映了这一点。
并且由于Python函数(是否包装在方法中)可以与任何Python类型一起使用(如果如此设计),未绑定的method
对象支持__get__
,因此您可以使用任何此类对象并坚持使用它进入另一个类;通过支持__get__
,他们支持重新绑定到新类。
如果要使用Python类型实现相同的目的,则必须将函数对象包装在自定义描述符中,然后实现自己的__get__
行为以限制可接受的行为。
请注意,在Python 3中,function.__get__(None, classobject)
仅返回函数对象本身,而不是像Python 2那样返回未绑定的方法对象。没有发现整个未绑定/绑定方法的区别(其中未绑定方法对象在调用时限制第一个参数的类型)有用,因此将其删除。