<p>用户定义的类实例可以在运行时添加/删除属性:</p>
<pre><code>>>> class A(object): pass
...
>>> a = A()
>>> a.something = 1 #no error. Now a has a new something attibute
>>>
</code></pre>
<p>虽然内置类型通常不允许这样做:</p>
<pre><code>>>> a = object()
>>> a.something = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'something'
</code></pre>
<p>在python中,每个对象都有一个包含其属性的关联字典:<code>__dict__</code>。这本词典是可变的。执行任务时:</p>
<pre><code>instance.attribute = value
</code></pre>
<p>实际发生的情况是,您正在为对象的<code>__dict__</code>赋值:</p>
<pre><code>instance.__dict__['attribute'] = value
</code></pre>
<p>事实上:</p>
<pre><code>>>> class A(object):
... def __init__(self):
... self.something = 1
...
>>> a = A()
>>> a.__dict__
{'something': 1}
>>> a.other = 2
>>> a.__dict__
{'other': 2, 'something': 1}
>>> a.__dict__['other2'] = 3
>>> a.other2
3
</code></pre>
<p><a href="https://docs.python.org/2/reference/datamodel.html#object.__init__" rel="nofollow">^{<cd3>}</a>在这方面并不特别。这只是一个<em>约定</em>所有的属性都在那里定义,但是当你把<code>self.attribute = value</code>放在<code>__init__</code>里面时,你做的事情和上面的代码完全一样:创建一个新的<em>属性。
这是大多数时候进行初始化的正确方法</p>
<p>类不(通常)声明其实例的预定义属性集。使用某些元编程可以添加此类声明(例如,使用类修饰符/元类)</p>
<p>如果要提前定义类的属性,可以使用<a href="https://docs.python.org/2/reference/datamodel.html#slots" rel="nofollow">^{<cd6>}</a>:</p>
<pre><code>>>> class A(object):
... __slots__ = ('something',)
...
>>> a = A()
>>> a.something = 1
>>> a.other = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'other'
</code></pre>
<p>在类中定义<code>__slots__</code>时,它的实例没有关联的<code>__dict__</code>,因此无法在运行时添加属性</p>
<pre><code>>>> a.__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute '__dict__'
</code></pre>
<p>或者,您可以重新定义<a href="https://docs.python.org/2/reference/datamodel.html#object.__setattr__" rel="nofollow">^{<cd9>}</a>方法,以便更好地控制设置属性时发生的事情</p>