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

2024-12-27 08:47:00
admin
原创
127
摘要:问题描述:因此,我在回答这个问题时使用 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大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1579  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1355  
  信创产品在政府采购中的占比分析随着信息技术的飞速发展以及国家对信息安全重视程度的不断提高,信创产业应运而生并迅速崛起。信创,即信息技术应用创新,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。政府采购作为推动信创产业发展的重要力量,其对信创产品的采购占比情况备受关注。这不仅关系到信创产业的发展前...
信创和国产化的区别   8  
  信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,摆脱对国外技术的依赖。近年来,国货国用信创发展势头迅猛,在诸多领域取得了显著成果。这一发展趋势对科技创新产生了深远的推动作用,不仅提升了我国在信息技术领域的自主创新能力,还为经济社会的数字化转型提供了坚实支撑。信创推动核心技术突破信创产业的发展促使企业和科研...
信创工作   9  
  信创技术,即信息技术应用创新产业,旨在实现信息技术领域的自主可控与安全可靠。近年来,信创技术发展迅猛,对中小企业产生了深远的影响,带来了诸多不可忽视的价值。在数字化转型的浪潮中,中小企业面临着激烈的市场竞争和复杂多变的环境,信创技术的出现为它们提供了新的发展机遇和支撑。信创技术对中小企业的影响技术架构变革信创技术促使中...
信创国产化   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用