编程语言
首页 > 编程语言> > python – 哪一个是数据描述符和非数据描述符的正确定义?

python – 哪一个是数据描述符和非数据描述符的正确定义?

作者:互联网

它们都是来自文档的python

the first one说:

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).

the second one说:

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