<p>用户类被认为是可变的。Python没有(绝对)私有属性,因此您可以通过访问内部来更改类。</p>
<p>要将类用作<code>dict</code>中的键或将它们存储在<code>set</code>中,可以定义<a href="http://docs.python.org/reference/datamodel.html#object.__hash__" rel="noreferrer">^{<cd3>} method</a>和<a href="http://docs.python.org/reference/datamodel.html#object.__eq__" rel="noreferrer">^{<cd4>} method</a>,保证类是不可变的。在这种情况下,通常设计类API时不会在创建后对内部状态进行变异。</p>
<p>例如,如果引擎是由其id唯一定义的,则可以将其用作哈希的基础:</p>
<pre><code>class Engine(object):
def __init__(self, id):
self.id = id
def __hash__(self):
return hash(self.id)
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.id == other.id
return NotImplemented
</code></pre>
<p>现在可以在集合中使用类引擎的实例:</p>
<pre><code>>>> eng1 = Engine(1)
>>> eng2 = Engine(2)
>>> eng1 == eng2
False
>>> eng1 == eng1
True
>>> eng1 == Engine(1)
True
>>> engines = set([eng1, eng2])
>>> engines
set([<__main__.Engine object at 0x105ebef10>, <__main__.Engine object at 0x105ebef90>])
>>> engines.add(Engine(1))
>>> engines
set([<__main__.Engine object at 0x105ebef10>, <__main__.Engine object at 0x105ebef90>])
</code></pre>
<p>在上面的示例中,我向集合添加了另一个<code>Engine(1)</code>实例,但它被认为已经存在,并且集合没有更改。</p>
<p>注意,就列表而言,<code>.__eq__()</code>实现是最重要的;列表并不关心对象是否可变,但是使用<code>.__eq__()</code>方法,您可以测试给定引擎是否已经在列表中:</p>
<pre><code>>>> Engine(1) in [eng1, eng2]
True
</code></pre>