<p>你想做的只是起作用,但这不是个好主意。在</p>
<p>一般来说,重写时不希望以不兼容的方式更改方法的签名。这是<a href="https://en.wikipedia.org/wiki/Liskov_substitution_principle" rel="nofollow noreferrer">Liskov Substitution Principle</a>的一部分。在</p>
<p>在Python中,经常有很好的理由来违反继承并不总是关于子类型的。在</p>
<p>但是当你使用abc来定义一个接口时,这是关于子类型化的。这是<code>ABC</code>子类和<code>abstractmethod</code>修饰符的唯一目的,因此使用它们来表示其他任何东西充其量是高度误导的。在</p>
<hr/>
<p>更详细地说:</p>
<p>通过从<code>Agent</code>继承,可以声明<code>Clever_Agent</code>的任何实例都可以像<code>Agent</code>一样使用。这包括能够调用<code>my_clever_agent.perceive_world(my_observation)</code>。事实上,它不仅仅包括那些,这就是它的全部含义!如果这个调用总是失败的,那么no <code>Clever_Agent</code>是一个<code>Agent</code>,因此它不应该声明是。在</p>
<p>在某些语言中,您有时需要在接口检查时假装自己的方式,以便以后可以进行类型切换和/或“动态强制转换”回到实际类型。在Python中,这是不必要的。没有所谓的“列表<code>Agent</code>s”,只是任何东西的列表。(除非您使用可选的静态类型检查,但是在这种情况下,如果您需要绕过静态类型检查,不要声明一个静态类型只是为了给自己一个可以绕过的障碍。)</p>
<hr/>
<p>在Python中,可以通过添加可选参数将方法扩展到超类方法之外,这是完全有效的,因为它仍然与显式声明的类型兼容。例如,这是一件非常合理的事情:</p>
<pre><code>class Clever_Agent(Agent):
def perceive_world(self, observation, prediction=None):
print('I see %s' % observation)
if prediction is None:
print('I have no predictions about what will happen next')
else:
print('I think I am going to see %s happen next' % prediction)
</code></pre>
<p>甚至这可能是合理的:</p>
^{pr2}$