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

标签 python attributes language-design

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

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

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

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__:一个与对象关联的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__ (另外,还有一点开销)——因此 dint 实例可以具有任意属性,但您为此灵 active 付出了相当大的空间成本。

那么,如果您想要 int 仅具有 一个 额外属性 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/22846089/

相关文章:

python - 如何更改python中函数对象的属性?

programming-languages - 声明式编程语言的反馈,资源和信息

language-agnostic - 可以强制编译器实现对象不变性的OO语言列表

python - 如何找到数组中最常见的元素

python - 在 Python 中,是否可以调用类 A 的实例方法,但传入类 B 的实例?

javascript - jquery 在点击时在多个图像之间切换

jQuery 选择器没有特定的数据属性

c++ - "std::is_callable"在 C++17 中被 "std::is_invocable"替换了吗?

python - 如何在 python 中对列表中的数字求和?

python - 在 C/C++、Python 或 Fortran 中编程时输入方程式的方法