什么是动态调度和鸭子类型?

Posted

技术标签:

【中文标题】什么是动态调度和鸭子类型?【英文标题】:What is dynamic dispatch and duck typing? 【发布时间】:2018-07-25 14:15:54 【问题描述】:

在使用Pycharm的时候,经常会指出一个错误,说:

未解析的引用“名称”。此检查检测到的名称应该 解决但不解决。 由于动态调度和鸭子类型,这是 在有限但有用的情况下可能。***和 类级项目比实例项目更受支持。

我对此进行了窥探,但我发现的大多数问题和信息都是关于阻止显示消息的。我想知道的是:

什么是动态调度/鸭子类型? 这些“有用的案例数量”是什么(或示例)?

【问题讨论】:

【参考方案1】:

Python 使用鸭子类型约定。这意味着您不必指定名称的类型。例如,在 Java 中,您必须明确指定变量类型可以是 intObject。本质上,类型检查是在运行时完成的。

“如果它走路像鸭子,叫起来像鸭子,那它一定是鸭子。”

在 Python 中,一切似乎都可以正常工作,直到您尝试以非设计的方式操作对象。基本上,一个对象可能没有其他对象可能具有的特定方法或属性,并且直到 Python 在尝试它时抛出错误时您才会发现这一点。

动态调度是编译器或环境选择在运行时使用哪个版本的多态函数的做法。如果您有一个方法的多个实现,您可以以不同的方式使用它们,尽管这些方法具有相同或相似的属性/属性。这是一个例子:

class Foo:
   def flush():
       pass

class Bar:
    def flush():
       pass

两个类都有一个flush() 方法,但在运行时选择了正确的名称。

Python 不是这个过程的最佳示例,因为方法可以采用多个参数并且不必重新实现。 Java 是一个更好的例子,但我不够熟练,无法提供正确的例子。

【讨论】:

Duck 类型在某种意义上超越了类型检查。类型根本无关紧要,只要它提供正确的行为。如果一个函数期望一个参数有一个foo 方法,那么这个参数可以有任何类型,只要它提供foo。例如,它不必具有特定的foo-providing 祖先。真正的运行时类型检查将在第一次调用函数时强制执行参数的类型,而不是在第一次在函数体中使用参数时。【参考方案2】:

警告意味着您正在使用 PyCharm 无法识别的变量,但由于 Python 的动态特性,它无法确定它是否正确。

例如你可能有以下代码:

class myClass():

    def myfunc(self):
        print(self.name)

PyCharm 可能会抱怨self.name 无法解决。但是,您可以像这样使用该类:

my_class = myClass()
my_class.name = "Alastair"
my_class.myfunc()

这是完全有效的(尽管很脆弱)。

消息继续说它对不那么模棱两可的属性和方法更有信心。例如:

class myClass():
    my_instance_var = "Al"

    def myfunc(self):
        print(self.my_instance_var)

由于my_instance_var在源代码中定义(一个类属性),PyCharm可以确信它存在。

(除非你知道自己在做什么,否则不要使用类属性!)

【讨论】:

以上是关于什么是动态调度和鸭子类型?的主要内容,如果未能解决你的问题,请参考以下文章

py基础考察点

python 鸭子类型

鸭子类型

面向对象编程思想(前传)--你必须知道的javascript

python的鸭子类型与多态

python 鸭子类型