Python Can';t在“的实例上设置属性”;“对象”;班

Python Can';t在“的实例上设置属性”;“对象”;班,python,attributes,language-design,Python,Attributes,Language Design,所以,我在回答问题的时候正在玩弄Python,我发现这是无效的: o = object() o.attr = 'hello' 由于属性错误:“object”对象没有属性“attr”。但是,对于从对象继承的任何类,它都是有效的: class Sub(object): pass s = Sub() s.attr = 'hello' 打印s.attr会按预期显示“hello”。为什么会这样?Python语言规范中有什么规定您不能将属性分配给普通对象?这是Python的基本限制之一——您不

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

o = object()
o.attr = 'hello'
由于
属性错误:“object”对象没有属性“attr”
。但是,对于从对象继承的任何类,它都是有效的:

class Sub(object):
    pass

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

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

这是Python的基本限制之一——您不能重新打开类。不过,我相信实际的问题是由C中实现的类不能在运行时修改这一事实造成的。。。子类可以,但不能是基类。

这是Python的基本限制之一——不能重新打开类。不过,我相信实际的问题是由C中实现的类不能在运行时修改这一事实造成的。。。子类可以,但基类不能。这是因为对象是“类型”,而不是类。一般来说,C扩展中定义的所有类(如所有内置数据类型,以及numpy数组等)都不允许添加任意属性。

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

因此,在研究我自己的问题时,我发现了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'
>>类MyInt(int):
通过
>>>x=MyInt()
>>>打印x
0
>>>你好
>>>打印x。你好
4.
>>>x=x+1
>>>打印x
1.
>>>打印x。你好
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:“int”对象没有属性“hello”

我假设最后的错误是因为add函数返回一个int,所以我必须重写像
\uuuuu add\uuuu
这样的函数才能保留我的自定义属性。但现在,当我想到像“int”这样的“object”时,这一切对我来说是有意义的

因此,在研究我自己的问题时,我发现了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'
>>类MyInt(int):
通过
>>>x=MyInt()
>>>打印x
0
>>>你好
>>>打印x。你好
4.
>>>x=x+1
>>>打印x
1.
>>>打印x。你好
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:“int”对象没有属性“hello”

我假设最后的错误是因为add函数返回一个int,所以我必须重写像
\uuuuu add\uuuu
这样的函数才能保留我的自定义属性。但现在,当我想到像“int”这样的“object”时,这一切对我来说是有意义的

要支持任意属性分配,对象需要一个
\uuuu dict\uuuu
:一个与对象关联的dict,可以存储任意属性。否则,就没有地方放置新属性

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

例如,使用优秀的
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
…现在添加了
\uuuu dict\uuuuu
(另外,还有一点开销)——因此
dint
实例可以具有任意属性,但您需要为这种灵活性付出相当大的空间成本

那么,如果您希望
int
s只包含一个额外属性
foobar
。。。?这是一种罕见的需求,但Python确实为此提供了一种特殊的机制

>>> class fint(int):
...   __slots__ = 'foobar',
...   def __init__(self, x): self.foobar=x+100
... 
>>> asizeof.asizeof(fint(23))
80
…请注意,没有
int
那么小!(甚至两个
int
s,一个是
self
,另一个是
self.foobar
——第二个可以重新分配),但肯定比
力好得多

当类具有
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,只是一组有限的、僵硬的具有给定名称的“槽”(基本上每个槽可以容纳一个对某个对象的引用)


作为失去灵活性的交换,每个实例可以获得大量字节(只有在有无数实例的情况下才可能有意义,但是,这是有用例的)。

要支持任意属性分配,对象需要一个
\u dict\u
:一个与对象关联的dict,其中可以存储任意属性。否则,就没有地方放置新属性

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

例如,使用优秀的
pympler
projec