ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2019-08-29 21:57:35  阅读:236  来源: 互联网

标签:python-3-4 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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有