gpt4 book ai didi

python - 无法在 "object"类的实例上设置属性

转载 作者:IT老高 更新时间:2023-10-28 21:33:09 27 4
gpt4 key购买 nike

所以,我在回答 this question 时正在玩 Python ,我发现这是无效的:

o = object()
o.attr = 'hello'

由于 AttributeError: 'object' object has no attribute 'attr'。但是,对于从对象继承的任何类,它都是有效的:

class Sub(object):
pass

s = Sub()
s.attr = 'hello'

打印 s.attr 按预期显示“hello”。为什么会这样? Python 语言规范中有什么规定不能将属性分配给普通对象?


有关其他解决方法,请参阅 How can I create an object and add attributes to it? .

最佳答案

为了支持任意属性赋值,一个对象需要一个__dict__:一个与对象关联的字典,可以存储任意属性。否则,无处可放置新属性。

object 的实例 携带 __dict__ —— 如果确实如此,那么在可怕的循环依赖问题之前(因为 dict,像大多数其他东西一样,继承自 object;-),这将使 Python 中的 每个 对象都带有一个 dict,这意味着开销当前没有或不需要字典的每个对象有 许多 个字节(本质上,所有没有可任意分配属性的对象都没有或不需要字典)。

例如,使用优秀的 pympler 项目(您可以通过 svn 从 here 获取它),我们可以进行一些测量...:

>>> from pympler import asizeof
>>> asizeof.asizeof({})
144
>>> asizeof.asizeof(23)
16

您不会希望每个 int 占用 144 个字节而不是 16 个字节,对吧?-)

现在,当你创建一个类(从任何东西继承)时,事情就会改变......:

>>> class dint(int): pass
...
>>> asizeof.asizeof(dint(23))
184

...现在添加了 __dict__ is (加上,多了一点开销)——所以 dint 实例可以有任意属性,但您为这种灵 active 付出了相当大的空间成本。

那么,如果你想要 int 只带有 one 额外属性 foobar... 怎么办?这是一种罕见的需求,但 Python 确实为此目的提供了一种特殊的机制......

>>> class fint(int):
... __slots__ = 'foobar',
... def __init__(self, x): self.foobar=x+100
...
>>> asizeof.asizeof(fint(23))
80

...不像int那么相当,请注意! (甚至是两个 int,一个是 self,一个是 self.foobar - 第二个可以重新分配),但肯定是比 dint 好多了。

当类有 __slots__ 特殊属性(字符串序列),然后是 class 语句(更准确地说,默认元类,type) 确实为该类的每个实例配备 __dict__ (因此具有任意属性的能力),只是一组有限的、刚性的“槽”(基本上每个地方都可以使用给定的名称保存对某个对象的一个​​引用。

作为失去灵 active 的交换,您在每个实例中获得了大量字节(只有当您有数以万计的实例在运行时才有意义,但是,用例)。 p>

关于python - 无法在 "object"类的实例上设置属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1529002/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com