dict.fromkeys 等内置类型的函数描述符与普通方法的行为不同
function descriptor on builtin types like dict.fromkeys behaves different to a normal method
为什么 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])
由于函数描述符的类型错误而失败...:[=24=]
descriptor 'fromkeys' for type 'dict' doesn't apply to type 'list'
为什么python会这样区分内置函数和普通函数?我们也可以这样做吗?我们可以做一个只绑定到它所属的类型的函数吗?
class_or_type.descriptor
总是调用 descriptor.__get__(None, class_or_type)
,这就是为什么您无法从 内置 未绑定方法对象中获取 __get__
的原因。在 Python 2 函数上为 __get__
生成的(未绑定)method
类型显式实现了 __get__
,因为 Python 方法更加灵活。因此 builtin.descriptor
和 class.descriptor
都调用 .__get__()
,但是 returns 的对象类型不同,对于 Python 方法,对象类型代理属性访问:
通过__dict__
访问属性,另一方面,从不调用__get__
,所以class_or_type.__dict__['fromkeys']
给你原始的描述符对象。
在幕后,像 dict
这样的类型,包括它们的方法,是用 C 代码实现的,不在 Python 代码中,C 是很多对类型更挑剔。您永远不能使用旨在处理 dict
对象的内部实现细节的函数和列表,所以何必呢?
仅此而已;内置类型的方法与Python中实现的函数/方法不同,因此虽然它们大部分工作相同,它们不能使用动态类型,描述符如何工作的实现反映了这一点。
并且因为 Python 函数(包装在方法中或不包装),可以使用任何 Python 类型(如果这样设计的话),未绑定的 method
对象支持 __get__
这样你就可以把任何这样的东西粘在另一个东西上 class;通过支持 __get__
他们支持重新绑定到新的 class.
如果你想用 Python 类型实现同样的事情,你必须将函数对象包装在自定义描述符中,然后实现你自己的 __get__
行为来限制可接受的行为。
请注意,在 Python 3 中,function.__get__(None, classobject)
只是 returns 函数对象本身,而不是像 Python 2 那样的未绑定方法对象。整个未绑定/绑定方法的区别,其中未绑定方法对象在调用时限制第一个参数的类型,被发现并不是那么有用,所以它被删除了。
为什么 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])
由于函数描述符的类型错误而失败...:[=24=]
descriptor 'fromkeys' for type 'dict' doesn't apply to type 'list'
为什么python会这样区分内置函数和普通函数?我们也可以这样做吗?我们可以做一个只绑定到它所属的类型的函数吗?
class_or_type.descriptor
总是调用 descriptor.__get__(None, class_or_type)
,这就是为什么您无法从 内置 未绑定方法对象中获取 __get__
的原因。在 Python 2 函数上为 __get__
生成的(未绑定)method
类型显式实现了 __get__
,因为 Python 方法更加灵活。因此 builtin.descriptor
和 class.descriptor
都调用 .__get__()
,但是 returns 的对象类型不同,对于 Python 方法,对象类型代理属性访问:
通过__dict__
访问属性,另一方面,从不调用__get__
,所以class_or_type.__dict__['fromkeys']
给你原始的描述符对象。
在幕后,像 dict
这样的类型,包括它们的方法,是用 C 代码实现的,不在 Python 代码中,C 是很多对类型更挑剔。您永远不能使用旨在处理 dict
对象的内部实现细节的函数和列表,所以何必呢?
仅此而已;内置类型的方法与Python中实现的函数/方法不同,因此虽然它们大部分工作相同,它们不能使用动态类型,描述符如何工作的实现反映了这一点。
并且因为 Python 函数(包装在方法中或不包装),可以使用任何 Python 类型(如果这样设计的话),未绑定的 method
对象支持 __get__
这样你就可以把任何这样的东西粘在另一个东西上 class;通过支持 __get__
他们支持重新绑定到新的 class.
如果你想用 Python 类型实现同样的事情,你必须将函数对象包装在自定义描述符中,然后实现你自己的 __get__
行为来限制可接受的行为。
请注意,在 Python 3 中,function.__get__(None, classobject)
只是 returns 函数对象本身,而不是像 Python 2 那样的未绑定方法对象。整个未绑定/绑定方法的区别,其中未绑定方法对象在调用时限制第一个参数的类型,被发现并不是那么有用,所以它被删除了。