哪个是数据描述符和非数据描述符的正确定义? [英] which one is the right definition of data-descriptor and non-data descriptor?

查看:51
本文介绍了哪个是数据描述符和非数据描述符的正确定义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

它们都是来自文档的python:

Both of them are python from documents :

第一个说:

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

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

第二个说:

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

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__来制作数据描述符就够了吗?

The question is : is it enough to only define __set__ to make a data descriptor ?

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

And we I refer to the python source code, I found this :

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

似乎我们只能定义 __set__ 而没有 __get__.

Seems we can only define __set__ without __get__.

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

And then I turn to write some examples to prove what I got :

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

According to the python attribute lookup orders : the priority of data descriptor is higher than obj.__dict__.

我的示例显示:只有描述符同时定义了 __set____get__ 使其成为数据描述符!

My example shows : Only the descriptor defines both __set__ and __get__ makes it a data descriptor !

哪个是正确答案?

__set__ --- > 数据描述符

__set__ --- > data descriptor

__get____set__ ---> 数据描述符 ?

__get__ and __set__ ---> data descriptor ?

推荐答案

第二个引用是正确的.第二个引用来自 Python 语言参考(虽然你'提供了错误的链接),并且语言参考被认为比操作指南更权威.此外,它与实际行为相匹配;PyDescr_IsData 宏你发现的是object中使用的实际例程.__getattribute__ 确定什么算作数据描述符,以及 无论是 __set__ 还是 __delete__ 都会导致 tp_descr_set 为非空.

The second quote is correct. The second quote comes from the Python language reference (though you've provided the wrong link), and the language reference is considered more authoritative than how-to guides. Also, it matches the actual behavior; the PyDescr_IsData macro you found is the actual routine used in object.__getattribute__ to determine what counts as a data descriptor, and either __set__ or __delete__ will cause tp_descr_set to be non-null.

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

The language reference also explains why Set doesn't override the instance dict for a.b:

如果它没有定义__get__(),那么访问该属性将返回描述符对象本身,除非该对象的实例字典中有一个值.[...] 定义了 __set__() __get__() 的数据描述符总是覆盖实例字典中的重定义.

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 将退回到正常的属性查找行为,就好像它根本不是描述符一样.

Defining either __set__ or __delete__ will set a type's tp_descr_set slot and make instances of the type data descriptors. A data descriptor will always be invoked for attempts to set or delete the attribute it manages, even if there is an entry in the instance's dict with the same name, and even if it only has __set__ and you're trying to delete the attribute or vice versa. (If it doesn't have the needed method, it will raise an exception.) If a data descriptor also has __get__, it will also intercept attempts to get the attribute; otherwise, Python will fall back on the normal attribute lookup behavior, as if it wasn't a descriptor at all.

这篇关于哪个是数据描述符和非数据描述符的正确定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆