6

如果我制作这样的类实例

class MyClass(object):
    pass
x = MyClass()

然后我可以在 x 上设置属性,如下所示:

x.myAttr = 1或者x.__setattr__('myAttr', 1)

但是,如果我做一个 dict

d = {}

我无法在其上设置属性。例如,如果我这样做

d.__setattr__('myAttr', 1)

我得到错误“'dict'对象没有属性'myAttr'”如果我尝试也会发生同样的事情

d.myAttr = 1

我注意到在 x.myAttr = 1 的情况下,实际发生的是

x.__dict__

用新密钥更新,所以它必须是

d.__setattr__

不起作用,因为 d 没有

d.__dict__

仅仅因为 d一个字典。如果有人能彻底解释这里发生了什么,我将不胜感激。

所有 python 对象都有.__dict__吗?

为什么我尝试调用会d.__setattr__导致错误提示该属性不存在?

是否有我应该知道的内置类型的特定层次结构?一个简单的参考将不胜感激。

蟒蛇2.6.4

Windows XP 专业版 x64 SP2

4

5 回答 5

5

dict实例没有属性__dict__,因此您不能为其分配属性。大多数 Python 的内置类(用 C 语言编写并以不同方式定义属性)没有。如果您 subclass dict,则子类将具有一个__dict__属性,然后您可以将属性添加到子类的实例中。

于 2012-06-05T17:51:12.370 回答
3

从 docs.python.org 复制粘贴:

每个模块的一个特殊属性是 __dict__。这是包含模块符号表的字典。修改这个字典实际上会改变模块的符号表,但是不能直接赋值给__dict__属性(可以写m.__ dict__['a'] = 1,它定义ma为1,但不能写m.__dict__ = {})。不建议直接修改 __dict__。

http://docs.python.org/library/stdtypes.html

方法

两条线都做同样的事情:

x.__setattr__('a', b)
x.a = b

像 __ add__ 是:

x.__add__(b)
x + b

但是,您可以将 dict.__ setattr__ 函数重新定义为您想要的任何内容

编辑第三条评论:

class x(object):
    def __init__(self):
        pass
    def __setattr__(self, a, b):
        print "nope, i will not set the attribute %s = %s" % (a,b)

c = x()
c.a = 4
print c.__dict__

将打印“不,我不会设置属性 a = 4 并且c.__dict__不会有属性 'a'

于 2012-06-05T17:43:40.310 回答
1

异常说明:

>>> class C(object):
...     __slots__ = ('a', 'b')
... 
>>> c = C()
>>> c.a = 1
>>> c.t = 2
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'C' object has no attribute 't'

此处描述的插槽

于 2012-06-05T17:43:30.810 回答
0

self.__dict__是一个dict。假设,dict也有一个__dict__,它的递归定义和事情不会工作:-)

于 2013-05-02T19:03:19.190 回答
0

如果你这样做x.myAttr = 1了,你就真的在做x.__dict__['myAttr'] = 1。如果你这样做了x.__dict__.myAttr,你会得到与d.myAttr. 这 。attribute赋值是为类定义的,但不是字典 - 字典赋值是 via d['attribute']

于 2015-10-27T15:31:26.623 回答