无法在“对象”类的实例上设置属性

2024-12-27 08:47:00
admin
原创
126
摘要:问题描述:因此,我在回答这个问题时使用 Python 进行了一些尝试,我发现这是无效的:o = object() o.attr = 'hello' 由于AttributeError: 'object' object has no attribute 'attr'。但是,对于从 object 继承的任何类,它都...

问题描述:

因此,我在回答这个问题时使用 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 语言规范中哪一项规定不能为 vanilla 对象分配属性?


有关其他解决方法,请参阅如何创建对象并向其添加属性?。


解决方案 1:

为了支持任意属性赋值,对象需要一个__dict__:与对象关联的字典,其中可以存储任意属性。否则,就没有地方放置新属性。

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

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

>>> 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实例可以具有任意属性,但是您需要为这种灵活性付出相当大的空间成本。

那么,如果您int只想要一个额外属性foobar,该怎么办?这种情况很少见,但 Python 确实为此提供了一种特殊机制……

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

...请注意,它不如那么int!(或者甚至是两个ints,一个是 theself和一个 the self.foobar-- 第二个可以重新分配),但肯定比 好得多dint

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

作为失去灵活性的交换,每个实例可以获得很多字节(可能只有当您有无数个实例在四处移动时才有意义,但是,有这样的用例)。

解决方案 2:

正如其他回答者所说,object没有__dict__。是所有object类型的基类,包括或。 因此 提供的任何内容对他们来说也是一种负担。 即使是像可选这样简单的东西也需要每个值都有一个额外的指针; 这会为系统中的每个对象浪费额外的 4-8 字节内存,但实用性非常有限。int`str`object __dict__


在 Python 3.3+ 中,您可以(并且应该)使用它,而不必创建虚拟类的实例types.SimpleNamespace

解决方案 3:

这仅仅是由于优化。

字典相对较大。

>>> import sys
>>> sys.getsizeof((lambda:1).__dict__)
140

大多数(可能是所有)用 C 语言定义的类都没有用于优化的字典。

如果你查看源代码,你会发现有很多检查来查看对象是否有字典。

解决方案 4:

因此,在调查我自己的问题时,我发现了有关 Python 语言的这一点:你可以从 int 之类的东西继承,并且你会看到相同的行为:

>>> class MyInt(int):
       pass

>>> x = MyInt()
>>> print x
0
>>> x.hello = 4
>>> print x.hello
4
>>> x = x + 1
>>> print x
1
>>> print x.hello
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
AttributeError: 'int' object has no attribute 'hello'

我猜想最后的错误是因为 add 函数返回一个 int,所以我必须重写类似__add__这样的函数才能保留我的自定义属性。但是当我想到“对象”就像“int”时,这一切对我来说都是有意义的(我认为)。

解决方案 5:

https://docs.python.org/3/library/functions.html#object

注意object没有__dict__所以不能将任意属性分配给类的实例object

解决方案 6:

这是因为 object 是一种“类型”,而不是类。通常,C 扩展中定义的所有类(例如所有内置数据类型以及 numpy 数组等)都不允许添加任意属性。

解决方案 7:

这是(在我看来)Python 的一个基本限制 - 您无法重新打开类。但我认为实际问题是由于在 C 中实现的类无法在运行时修改...子类可以,但基类不能。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用