无法设置对象类的属性 [英] Can't set attributes of object class
问题描述
所以,我与Python玩弄一边回答<一个href=\"http://stackoverflow.com/questions/1528932/how-to-create-inline-objects-with-properties-in-python/\">this问题,我发现这是无效的:
So, I was playing around with Python while answering this question, and I discovered that this is not valid:
o = object()
o.attr = 'hello'
由于一个 AttributeError的:'对象'对象有没有属性'ATTR
。然而,从对象继承的任何类,它是有效的:
due to an AttributeError: 'object' object has no attribute 'attr'
. However, with any class inherited from object, it is valid:
class Sub(object):
pass
s = Sub()
s.attr = 'hello'
印刷 s.attr
显示'你好'预期。为什么会出现这样的情况?在Python语言规范什么规定,你不能分配属性香草对象?
Printing s.attr
displays 'hello' as expected. Why is this the case? What in the Python language specification specifies that you can't assign attributes to vanilla objects?
推荐答案
的实例对象
做的不可以随身携带 __字典__
- 如果它这样做了,可怕的循环依赖问题(因为字典
之前,像其他大多数的一切,从<$ C $继承C>对象 ;-),这将鞍的每个的对象在Python有字典,这将意味着的许多的每个对象的字节的开销,目前没有或需要一个字典(基本上,没有随意分配的属性不具备或需要的字典中的所有对象)。
An instance of object
does not carry around a __dict__
-- if it did, before the horrible circular dependence problem (since dict
, like most everything else, inherits from object
;-), this would saddle every object in Python with a dict, which would mean an overhead of many bytes per object that currently doesn't have or need a dict (essentially, all objects that don't have arbitrarily assignable attributes don't have or need a dict).
例如,采用优 pympler
项目(您可以通过从的这里),我们可以做一些测量...
For example, using the excellent pympler
project (you can get it via svn from here), we can do some measurements...:
>>> from pympler import asizeof
>>> asizeof.asizeof({})
144
>>> asizeof.asizeof(23)
16
您不希望每 INT
占用144个字节,而不是仅仅16,右 - ?)
You wouldn't want every int
to take up 144 bytes instead of just 16, right?-)
现在,当你犯了一个类(无论从那个继承),事物的变化...
Now, when you make a class (inheriting from whatever), things change...:
>>> class dint(int): pass
...
>>> asizeof.asizeof(dint(23))
184
...的 __ __字典
的是的现在又增加了(加,多一点开销) - 因此力
实例可以拥有任意的属性,但是你付出相当的空间成本灵活性。
...the __dict__
is now added (plus, a little more overhead) -- so a dint
instance can have arbitrary attributes, but you pay quite a space cost for that flexibility.
所以,如果你想 INT
s的只是有一个的额外属性 foobar的
。 ..?这是一个难得的需要,但是Python的确为目的的特殊机制...
So what if you wanted int
s with just one extra attribute foobar
...? It's a rare need, but Python does offer a special mechanism for the purpose...
>>> class fint(int):
... __slots__ = 'foobar',
... def __init__(self, x): self.foobar=x+100
...
>>> asizeof.asizeof(fint(23))
80
......不是的非常的形成微小作为 INT
,你要知道! (甚至两个 INT
S,一个自
和一个 self.foobar
- 第二个可以被重新分配),但肯定远远好力
...not quite as tiny as an int
, mind you! (or even the two int
s, one the self
and one the self.foobar
-- the second one can be reassigned), but surely much better than a dint
.
在这个类有 __插槽__
特殊的属性(字符串序列),那么类
语句(更precisely,默认元类,键入
)做的不可以装备该类的每一个实例与 __字典__
(因此有任意属性的能力),只是一个有限的,刚性集插槽(可各持一个参考一些对象主要地方)用给定的名字。
When the class has the __slots__
special attribute (a sequence of strings), then the class
statement (more precisely, the default metaclass, type
) does not equip every instance of that class with a __dict__
(and therefore the ability to have arbitrary attributes), just a finite, rigid set of "slots" (basically places which can each hold one reference to some object) with the given names.
在换回失去的灵活性,你获得了很多每个实例的字节(前提是你有闲逛身边实例不计其数可能有意义的,但是,有是的用例的)。
In exchange for the lost flexibility, you gain a lot of bytes per instance (probably meaningful only if you have zillions of instances gallivanting around, but, there are use cases for that).
这篇关于无法设置对象类的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!