【问题标题】:which one is the right definition of data-descriptor and non-data descriptor?哪一个是数据描述符和非数据描述符的正确定义?
【发布时间】:2015-05-19 01:12:42
【问题描述】:

它们都是来自文档的python:

the first one 说:

如果一个对象同时定义了__get__()__set__(),它被认为是一个数据描述符。 只定义__get__()的描述符称为非数据描述符 (它们通常用于方法,但也可以用于其他用途)。

the second one 说:

如果描述符定义了__set__()和/或__delete__(),它是一个数据描述符;如果两者都没有定义,则它是非数据描述符。 通常,数据描述符定义__get__()__set__(),而非数据描述符只有__get__() 方法。

问题是:只定义__set__ 来制作数据描述符是否足够?

而我们我参考了python源代码,我发现了这个:

#define PyDescr_IsData(d) (Py_TYPE(d)->tp_descr_set != NULL)

看来我们只能定义__set__ 而没有__get__

然后我转而写一些例子来证明我得到了什么:

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 python-3.4


【解决方案1】:

第二句是正确的。第二个引用来自Python language reference(尽管您提供了错误的链接),并且语言参考被认为比操作指南更权威。此外,它与实际行为相匹配;您找到的PyDescr_IsData 宏是实际的例程used in object.__getattribute__,用于确定什么是数据描述符,either __set__ or __delete__ 将导致tp_descr_set 为非空。

语言参考还解释了为什么Set 不会覆盖a.b 的实例字典:

如果未定义__get__(),则访问该属性将返回描述符对象本身,除非该对象的实例字典中有值。 [...] 定义了__set__() __get__() 的数据描述符始终覆盖实例字典中的重新定义。

定义__set____delete__ 将设置类型的tp_descr_set 槽并创建类型数据描述符的实例。将始终调用数据描述符以尝试设置或删除它管理的属性,即使实例的 dict 中有一个具有相同名称的条目,即使它只有 __set__ 并且您试图删除属性,反之亦然。 (如果它没有所需的方法,它会引发异常。)如果数据描述符也有__get__,它也会拦截获取属性的尝试;否则,Python 将依赖正常的属性查找行为,就好像它根本不是描述符一样。

【讨论】:

    猜你喜欢
    • 2012-10-12
    • 1970-01-01
    • 2012-10-16
    • 1970-01-01
    • 1970-01-01
    • 2023-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多