当前位置: 首页 > 面试题库 >

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

易刚捷
2023-03-14
问题内容

它们都是文档中的python:

第一个说:

如果对象同时定义__get__()__set__(),则将其视为数据描述符。仅定义__get__()的描述符称为非数据描述符(它们通常用于方法,但也可以用于其他用途)。

第二个说:

如果描述符定义__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语言参考(尽管您提供了错误的链接),并且该语言参考被认为比使用指南更具权威性。而且,它与实际行为匹配;在PyDescr_IsData你发现宏是实际的程序中使用object.__getattribute__,以确定作为数据描述什么计数,并且无论是__set____delete__将导致tp_descr_set对非空。

语言参考还解释了为什么Set不覆盖以下实例的dict a.b

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

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



 类似资料:
  • Python 中,通过使用描述符,可以让程序员在引用一个对象属性时自定义要完成的工作。 本质上看,描述符就是一个类,只不过它定义了另一个类中属性的访问方式。换句话说,一个类可以将属性管理全权委托给描述符类。 描述符是 Python 中复杂属性访问的基础,它在内部被用于实现 property、方法、类方法、静态方法和 super 类型。 描述符类基于以下 3 个特殊方法,换句话说,这 3 个方法组成

  • 本节讨论了 Table , Column 和 MetaData 物体。 元数据实体的集合存储在适当命名的对象中。 MetaData :: from sqlalchemy import * metadata_obj = MetaData() MetaData 是一个容器对象,它将描述的数据库(或多个数据库)的许多不同功能放在一起。 要表示表,请使用 Table 班级。它的两个主要参数是表名,然后是

  • 问题内容: 什么是类描述符? 它是特定类的对象吗? 问题答案: 是的,对象是某个“类”的类描述符。 从API中: 此类的实例表示正在运行的Java应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组还属于一个反映为Class对象的类,该类对象由元素类型和维数相同的所有数组共享。原始Java类型(布尔型,字节型,字符型,短型,整型,长型,浮点型和双精度型)以及关键字void也都表示为对象。

  • 文件描述符 Linux很重要的设计思想就是一切皆文件,网络是文件,键盘等外设也是文件,很神奇吧?于是所有资源都有了统一的接口,开发者可以像写文件那样通过网络传输数据,我们也可以通过/proc/的文件看到进程的资源使用情况。 内核给每个访问的文件分配了文件描述符(File Descriptor),它本质是一个非负整数,在打开或新建文件时返回,以后读写文件都要通过这个文件描述符了。 应用 我们想想操作

  • 文件描述符接口 函数 int  fd_new (void)   分配文件描述符   struct dfs_fd *  fd_get (int fd)   获取文件描述结构   void  fd_put (struct dfs_fd *fd)   放置文件描述符   int  fd_is_open (const char *pathname)   判断文件是否已被打开   int  select (

  • 这个版本规范的部署描述文件可在此下载:http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd

  • 本章指定的 Java™ Servlet 规范要求 Web 容器支持部署描述文件。部署描述文件表达了应用开发人员、应用集成人员和 Web 应用部署人员之间的元素和配置信息。 对于 Java Servlet 2.4 和以后的版本,部署描述文件在 XML 模式文档中定义。 为了向后兼容到2.2版本的API编写的应用程序,Web 容器也需要支持2.2版本的部署描述文件。为了向后兼容2.3版本的API编写的

  • 当我在Weblogic 10.3.6中部署WAR时,它会运行,但在Weblogic 10.3.0中,它会抛出以下内容: 无法加载描述符D:\bea103\user_projects\domain\SRVWinplex\Deployments\WinplexA模块WinplexA的oader2.java:768weblogic.servlet.internal.错误是escriptor.get描述符