getset_descriptor

2023-11-08

>>> class A(object): pass
... 
>>> A.__dict__
<dictproxy object at 0x173ef30>
>>> A.__dict__.__dict__
Traceback (most recent call last):
  File "<string>", line 1, in <fragment>
AttributeError: 'dictproxy' object has no attribute '__dict__'
>>> A.__dict__.copy()
{'__dict__': <attribute '__dict__' of 'A' objects> ... }
>>> A.__dict__['__dict__']
<attribute '__dict__' of 'A' objects> # What is this object?

If I do A.something = 10, this goes into A.__dict__. What is this <attribute '__dict__' of 'A' objects> found in A.__dict__.__dict__, and when does it contain something?

asked  Feb 2 '11 at 16:52
porgarmingduod
2,830 1 27 60
 
3  
A more suitable example variable would've been ive. At least it would've made this a moreA.__dict__['ive'] question ;) I'll see myself out –  Joakim  Oct 1 '15 at 15:01

4 Answers

up vote 60 down vote accepted

First of all A.__dict__.__dict__ is different from A.__dict__['__dict__'], and the former doesn't exist. The latter is the __dict__ attribute that the instances of the class would have. It's a descriptor object that returns the internal dictionary of attributes for the specific instance. In short, the __dict__attribute of an object can't be stored in object's __dict__, so it's accessed through a descriptor defined in the class.

To understand this, you'd have to read the documentation of the descriptor protocol.

The short version:

  1. For an instance of class A, access to instance.__dict__ is provided by A.__dict__['__dict__'] which is the same as vars(A)['__dict__'].
  2. For the class A, access to A.__dict__ is provided by type.__dict__['__dict__'] (in theory) which is the same as vars(type)['__dict__'].

The long version:

Both classes and objects provide access to attributes both through the attribute operator (implemented via the class or metaclass's __getattribute__), and the __dict__ attribute/protocol which is used by vars(ob).

For normal objects, the __dict__ object creates a separate dict object, which stores the attributes, and __getattribute__ first tries to access it and get the attributes from there (before attempting to look for the attribute in the class by utilizing the descriptor protocol, and before calling __getattr__). The __dict__ descriptor on the class implements the access to this dictionary.

  • x.name is equivalent to trying those in order: x.__dict__['name']type(x).name.__get__(x, type(x))type(x).name
  • x.__dict__ does the same but skips the first one for obvious reasons

As it's impossible for the __dict__ of instance to be stored in __dict__ of the instance, it is accessed through the descriptor protocol directly instead, and is stored in a special field in the instance.

A similar scenario is true for classes, although their __dict__ is a special proxy object that pretends to be a dictionary (but might not be internally), and doesn't allow you to change it or replace it with another one. This proxy allows you, among all else, to access the attributes of a class that are specific to it, and not defined in one of its bases.

By default, a vars(cls) of an empty class carries three descriptors - __dict__ for storing the attributes of the instances, __weakref__ which is used internally by weakref, and the docstring of the class. The first two might be gone if you define __slots__. Then you wouldn't have __dict__ and __weakref__ attributes, but instead you'd have a single class attribute for each slot. The attributes of the instance then wouldn't be stored in a dictionary, and access to them will be provided by the respective descriptors in the class.


And lastly, the inconsistency that A.__dict__ is different from A.__dict__['__dict__'] is because the attribute __dict__ is, by exception, never looked up in vars(A), so what is true for it isn't true for practically any other attribute you'd use. For example, A.__weakref__ is the same thing as A.__dict__['__weakref__']. If this inconsistency didn't exist, using A.__dict__ would not work, and you'd have to always use vars(A) instead.

answered  Feb 2 '11 at 17:26
Rosh Oxymoron
9,112 1 24 36
 
5  
Thanks for the detailed answer. Although I had to read it a few times, I think it has been a while since I learned so many new details of Python. –  porgarmingduod  Feb 3 '11 at 12:52

Since A.__dict__ is a dictionary storing A attributes, A.__dict__['__dict__'] is the direct reference to that same A.__dict__ attribute.

A.__dict__ contains a (kind-of) reference to itself. The "kind-of" part is why the expression A.__dict__ returns a dictproxy instead of a normal dict.

>>> class B(object):
...     "Documentation of B class"
...     pass
...
>>> B.__doc__
'Documentation of B class'
>>> B.__dict__
<dictproxy object at 0x00B83590>
>>> B.__dict__['__doc__']
'Documentation of B class'
answered  Feb 2 '11 at 17:14
vz0
19k 6 20 52
 
5  
A.__dict__['__dict__'] isn't a reference to A.__dict__. It implements the __dict__ attribute of the instances. To try this for yourself, A.__dict__['__dict__'].__get__(A(), A) returns the attributes ofA(), while A.__dict__['__dict__'].__get__(A, type) fails. –  Rosh Oxymoron  Feb 2 '11 at 17:37

Lets do some exploring!

>>> A.__dict__['__dict__']
<attribute '__dict__' of 'A' objects>

I wonder what that is?

>>> type(A.__dict__['__dict__'])
<type 'getset_descriptor'>

What attributes does a getset_descriptor object have?

>>> type(A.__dict__["__dict__"]).__dict__
<dictproxy object at 0xb7efc4ac>

By making a copy of that dictproxy we can find some interesting attributes, specifically __objclass__ and __name__.

>>> A.__dict__['__dict__'].__objclass__, A.__dict__['__dict__'].__name__
(<class '__main__.A'>, '__dict__')

So __objclass__ is a reference to A and __name__ is just the string '__dict__', name of an attribute perhaps?

>>> getattr(A.__dict__['__dict__'].__objclass__, A.__dict__['__dict__'].__name__) == A.__dict__
True

There we have it! A.__dict__['__dict__'] is an object that can refer back to A.__dict__.

answered  Feb 2 '11 at 17:38
Andrew Clark
101k 8 125 188
 
 
PEP 252 says that __objclass__ is the class that defined this attribute, not that is an attribute of that class. This makes your getattr example incorrect. A more correct one would begetattr(A().__dict__['__dict__'].__objclass__, A.__dict__['__dict__'].__name__) –  Rosh Oxymoron  Feb 2 '11 at 17:48

You can try the following simple example to understand more of this:

>>> class A(object): pass
... 
>>> a = A()
>>> type(A)
<type 'type'>
>>> type(a)
<class '__main__.A'>
>>> type(a.__dict__)
<type 'dict'>
>>> type(A.__dict__)
<type 'dictproxy'>
>>> type(type.__dict__)
<type 'dictproxy'>
>>> type(A.__dict__['__dict__'])
<type 'getset_descriptor'>
>>> type(type.__dict__['__dict__'])
<type 'getset_descriptor'>
>>> a.__dict__ == A.__dict__['__dict__'].__get__(a)
True
>>> A.__dict__ == type.__dict__['__dict__'].__get__(A)
True
>>> a.__dict__ == type.__dict__['__dict__'].__get__(A)['__dict__'].__get__(a)
True

From the above example, it seems that class objects attributes are stored by their class, class's attributes are stored by their class, which are metaclasses. This is also validated by:

>>> a.__dict__ == A.__getattribute__(a, '__dict__')
True
>>> A.__dict__ == type.__getattribute__(A, '__dict__')
True
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

getset_descriptor 的相关文章

随机推荐

  • jieba自定义分词规则与多进程切词

    当存在某些自定义的专业名称或长词时 jieba有可能会当成多个词 但其实是一个词 自定义的方法如下 原始的jieba效果 import jieba if name main sentence 学习python与人工智能有益身体健康 ret
  • ubuntu常用命令(转载)

    ls 列出当前目录文件 不包括隐含文件 ls a 列出当前目录文件 包括隐含文件 ls l 列出当前目录下文件的详细信息 cd 回当前目录的上一级目录 cd 回上一次所在的目录 cd 或 cd 回当前用户的宿主目录 mkdir 目录名 创建
  • ide运行报错“Command line is too long”解决办法

    有时运行程序时 ide会报如下错 如何解决呢 其实提示已经告诉你解决办法了 点击图中的蓝色超链接 JAR MAINIFEST 或 CLASSPATH FILE 都能解决问题 这是因为命名的方法名太长了才会报这个错 方法2 如果没有弹窗 也可
  • 查看Linux下rpm文件安装到哪个路径

    命令 root localhost rpm qpl xxx rpm more
  • 用户数据报UDP

    UDP概述 UDP 只在 IP 的数据报服务之上增加了很少一点的功能 即端口的功能和差错检测的功能 UDP 的主要特点 UDP 是无连接的 不需要建立连接 直接发送数据 发送完以后也不需要释放连接 UDP 使用尽最大努力交付 即不保证可靠交
  • 使用 MATLAB 绘制爱心:帮助你成功表白

    作者简介 人工智能专业本科在读 喜欢计算机与编程 写博客记录自己的学习历程 个人主页 小嗷犬的个人主页 个人网站 小嗷犬的技术小站 个人信条 为天地立心 为生民立命 为往圣继绝学 为万世开太平 本文目录 MATLAB 绘制爱心 方法一 方法
  • C++中string的size与length的区别

    在C 的string类中 有两种函数 length和size 他们的作用都是返回字符串的长度 那么 问题来了 他们两者有什么区别 为了钻研 我们要先找到他们两者的源代码 让我们先找到length的源代码 首先 我们随便定义一个字符串 并调用
  • hualinux dj3 2.4:drf普通视图generics及例子

    目录 一 关于通用视图generics 1 1 基于类的视图 1 2 关于通用视图 1 2 1 介绍 1 2 2 属性 1 2 3 方法 1 2 4 Mixins 1 2 5 具体的通用视图 1 2 6 其它 二 drf通用视图generi
  • 内核调试手段

    1 内核调试配置选项 内核拥有多项用于调试的功能 但是这些功能会造成额外的输出并导致性能下降 因此 内核通常都是禁止掉调试功能 内核调试相关的配置项主要集中在内核配置菜单 Kernel hacking 中 在使用下面的调试手段时 先确保内核
  • 如何修改unity项目名称

    在Unity中 修改项目名称需要对一些文件和设置进行修改 以下是修改Unity项目名称的步骤 在Unity编辑器中 选择项目文件夹 Project 面板中的 Assets 然后点击右键 在弹出菜单中选择 Show in Explorer 在
  • 项目管理利器—maven

    一 简介 maven是优秀的项目管理和构建工具 能让我们更为方便的来管理和构建项目 从最基础的环境配置 到maven核心知识点的应用 使用maven来构建和管理Java项目 Maven是基于项目对象模型 POM 可以通过一小段描述信息来管理
  • JavaScript数组中筛选相同的元素组成新数组

    var college type 2 lastName 孙策 type 1 lastName 后裔 type 3 lastName 阿木木 type 3 lastName 亚索 type 1 lastName 剑魔 type 1 lastN
  • 写给我的2015—开启工作新旅程

    前沿 2015年的总结相比2014年来的晚了许多 原因一方面是今年呀的发现CSDN竟然没有了前两年写年终的活动 另一方面嘛还是自己太懒散了 一直恍恍惚惚的没有下手来总结 今天 在这小年夜里 ps 外面下完雪挺冷的 独自一个人坐在办公桌前 静
  • 实心球体内部电势计算公式_均匀带电球体中心点电势怎么求

    展开全部 公式 q 其中 为电势能 q为电荷量 为电势 即 q 均匀带电球内的电场分布和距离球心的距32313133353236313431303231363533e4b893e5b19e31333431363565离r成正比 解析 由于正
  • linux文件权限查看及修改-chmod ------入门的一些常识

    查看linux文件的权限 ls l 文件名称ULUitugULUitug查看linux文件夹的权限 ls ld 文件夹名称 所在目录 ULUitugULUitug修改文件及文件夹权限 ULUitugULUitugsudo chmod 代表类
  • 【软件工程】内聚

    概念 是指一个模块内部个成分之间相互关联程度的度量 也就是说 凝聚是对模块内各处理动作组合强度的一种度量 很显然 一个模块的内聚越大越好 偶然凝聚 一个模块内的各处理元素之间没有任何联系 只是偶然地被凑到一起 这种模块也称为巧合内聚 内聚程
  • MySQL数据库引擎InnoDB和MyISAM的区别?

    数据库引擎InnoDB和MyISAM的区别 1 MyISAM不支持事务 InnoDB支持事务 2 MyISAM支持全文索引 InnoDB在MySQL5 6之前不支持 3 MyISAM不支持外键 InnoDB支持外键 4 MyISAM只支持表
  • STM32之flash的读写

    本文内容 本实验主要介绍Flash地址空间的数据读取 一 创建STM32CUBEMX工程 芯片选择F103C8 配置定时器 打开外部时钟 配置时钟 配置PC13为output对应板子上的LED 设置堆栈大小为4K 导出 二 KEIL下的配置
  • Vue 3 第七章:computed计算属性

    文章目录 1 Vue3中的computed函数 1 1 什么是computed 1 2 如何定义computed 1 3 computed函数的使用场景 1 3 1 过滤和排序 1 3 1 数组计算 2 computed函数的原理 总结 1
  • getset_descriptor

    What is the dict dict attribute of a Python class up vote 43 down vote favorite 23 gt gt gt class A object pass gt gt gt