擅长:python、mysql、java
<p>我认为这是一个有点欺骗性的例子;有些事情你还没有说。我猜,当你说你“有一个接口”时,你的意思是你有一些代码接受一个对象并调用它的<code>run</code>方法。在</p>
<p>如果在调用该对象的<code>run</code>方法之前没有测试该对象的类型,那么您使用的是duck类型,简单明了!(在本例中,如果它有一个<code>run</code>方法,那么它就是一个<code>Runner</code>)只要你不在对象上使用<code>type</code>或{<cd6>},那么你就是python了。在</p>
<p>是接受纯字符串还是只接受节点对象的问题是一个微妙的不同问题。字符串和<code>node</code>对象可能根本没有实现相同的接口!字符串基本上不会像<code>node</code>那样呱呱叫,所以你不必把它们当作一个。这就像大象来了,如果你想让它像鸭子一样嘎嘎叫,你必须给大象一个磁带播放器,并训练大象先使用它。在</p>
<p>所以这不再是“鸭子类型”的问题,而是界面设计的问题。你正试图决定你希望你的接口有多严格。在</p>
<p>为了给你一个答案,那么,在这个层次上,我认为假设<code>run</code>返回一个<code>node</code>对象是最具python风格的。不需要使用<code>isinstance</code>或<code>type</code>来测试。假设它是一个<code>node</code>对象,如果使用你的接口的程序员弄错了,并且看到了一个异常,那么他们必须读取你的docstring,这将告诉他们<code>run</code>应该传递一个<code>node</code>对象。在</p>
<p>然后,如果您希望<em>也接受字符串或类似字符串的东西,您可以这样做。由于字符串是相当原始的类型,我想说使用<code>isinstance(obj, basestring)</code>(但是<em>不是</em><code>type(obj) == str</code>,因为它拒绝unicode字符串,等等)。本质上,这就是你对你的程序的懒惰用户非常宽容和友好;你已经超越了接受大象和像鸭子一样呱呱叫的东西。在</p>
<p>(更具体地说,我想说这有点像在函数的开头调用<code>iter</code>来同时接受生成器和序列)</p>