<p>要修复此问题,只需交换<code>Child</code><code>__init__</code>中的初始化顺序,这样<code>Child.__getitem__</code>所需的<code>Child</code>属性在需要之前被初始化:</p>
<pre><code>def __init__(self, name, gender, age=None):
print('call __init__ Child')
self._age = age
super(Child, self).__init__(name, gender)
</code></pre>
<p>这个修复对于这个特定的场景是唯一的,但是它通常也是正确的修复;一般来说,父类的唯一责任是不要不必要地中断子类化,但是不能期望它们计划让子类创建新的类不变量,并尝试预先适应它们。子类应该完全了解父类,子类的责任是确保它不会破坏父类的任何行为,在这种情况下,通过确保在父类可能使用需要它们的方法之前定义了所有新的必需属性。在</p>
<p>至于它为什么调用子类的<code>__getitem__</code>,这就是子类化的默认工作方式(不仅在Python中,而且在大多数OO语言中)。<code>Father.__init__</code>从<code>Child.__init__</code>接收的<code>self</code>仍然是<code>Child</code>对象,因此查找首先检查<code>Child</code>上的<code>__getitem__</code>。如果不这样做,您将有混乱的行为,其中一些索引在<code>Child</code>上调用<code>__getitem__</code>而有些没有,这将使它非常不直观。在</p>
<p>如果出于某种原因,您绝对必须在<code>Father.__init__</code>中只使用<code>Father</code>的<code>__getitem__</code>,那么您只需要明确您调用的是哪个方法。不要使用<code>self[gender]</code>或<code>self.__getitem__(gender)</code>(这两种方法都要经过正常的查找过程),do <code>Father.__getitem__(self, gender)</code>显式调用方法的<code>Father</code>版本(还需要显式地传递<code>self</code>,因为您使用的是未绑定方法而不是绑定方法)。在</p>
<p>在初始化过程中,父方法和子方法将不会被完全调用,因此在初始化过程中不会完全调用父方法:</p>
^{pr2}$