python – 哪一个是数据描述符和非数据描述符的正确定义?
作者:互联网
它们都是来自文档的python:
If an object defines both
__get__()
and__set__()
, it is considered a data descriptor.
Descriptors that only define__get__()
are called non-data descriptors
(they are typically used for methods but other uses are possible).
If the descriptor defines
__set__()
and/or__delete__()
, it is a data descriptor; if it defines neither, it is a non-data descriptor.
Normally, data descriptors define both__get__()
and__set__()
, while non-data descriptors have just the__get__()
method.
问题是:仅仅定义__set__来创建数据描述符是否足够?
我们参考python源代码,我发现了这个:
#define PyDescr_IsData(d) (Py_TYPE(d)->tp_descr_set != NULL)
似乎我们只能在没有__get__的情况下定义__set__.
然后我转而写一些例子来证明我得到了什么:
class GetSet(object):
def __get__(self, instance, cls =None):
print('__get__')
def __set__(self, obj, val):
print('__set__')
class Get(object):
def __get__(self, instance, cls =None):
print('__get__')
class Set(object):
def __set__(self, obj, val):
print('__set__')
class UserClass(object):
a = Get()
b = Set()
c = GetSet()
u = UserClass()
u.__dict__['a'] = 'a'
u.__dict__['b'] = 'b'
u.__dict__['c'] = 'c'
print('start')
print(u.a)
print(u.b)
print(u.c)
输出让我再次感到困惑:
start
a
b
__get__
None
根据python属性查找顺序:数据描述符的优先级高于obj .__ dict__.
我的例子显示:只有描述符定义__set__和__get__使它成为数据描述符!
哪一个是正确的答案?
__set__ —>数据描述符
要么
__get__和__set__ —>数据描述符?
解决方法:
第二个引用是正确的.第二个引用来自Python language reference(虽然您提供了错误的链接),并且语言参考被认为比操作指南更具权威性.此外,它符合实际行为;您找到的PyDescr_IsData
宏是确定什么算作数据描述符的实际例程used in object.__getattribute__
,而either __set__
or __delete__
将导致tp_descr_set为非空.
语言参考还解释了为什么Set不会覆盖a.b的实例dict:
If it does not define
__get__()
, then accessing the attribute will return the descriptor object itself unless there is a value in the object’s instance dictionary. […] Data descriptors with__set__()
and__get__()
defined always override a redefinition in an instance dictionary.
定义__set__或__delete__将设置类型的tp_descr_set槽并生成类型数据描述符的实例.即使实例的dict中有一个具有相同名称的条目,即使它只有__set__并且你试图删除属性或者反之亦然. (如果它没有所需的方法,则会引发异常.)如果数据描述符也有__get__,它也会拦截获取属性的尝试;否则,Python将依赖于正常的属性查找行为,就好像它根本不是描述符.
标签:python-3-4,python 来源: https://codeday.me/bug/20190829/1763787.html