什么是Python中的鸭子类型
在本教程中,我们将学习鸭子类型。这是Python中一个常用的术语,它源于一句话, “如果它走起来像鸭子、游泳像鸭子、看起来像鸭子,那么它可能就是只鸭子。”
上述陈述提供了一种识别鸭子的方法。在这里,我们不需要拥有鸭子的基因组序列。我们根据它的行为和外在表现得出结论。
我们将讨论鸭子类型在Python编程中的确切含义。
Python遵循 EAFP (宁愿请求宽恕,而不是征得许可)的哲学,而不是 LBLY (慎之又慎)。EAFP与”鸭子类型”风格有些相关。
动态类型与静态类型
使用鸭子类型的主要原因是为了支持 Python编程 中的动态类型。在Python中,我们不需要指定变量的数据类型,并且我们可以在后续代码中重新分配不同的数据类型值给同一个变量。让我们看下面的示例。
示例
x = 12000
print(type(x))
x = 'Dynamic Typing'
print(type(x))
x = [1, 2, 3, 4]
print(type(x))
输出:
<class 'int'>
<class 'str'>
<class 'list'>
正如我们在上面的代码中可以看到的,我们给变量x分配了一个整数,使其成为int类型。然后,我们给同一个变量分配了一个字符串和一个列表。Python解释器接受同一个变量的数据类型的更改。这是一种动态类型的行为。
许多其他编程语言如Java、Swift都是静态类型的。我们需要用数据类型声明变量。在下面的示例中,我们尝试使用Swift而不是Python来做相同的事情。
示例
# integer value assigning in JavaScript
var a = 10
# Assinging string in swift
a = 'Swift language'
以上代码无法编译,因为我们无法在Swift语言中将一个字符串赋值给一个整数变量 a 。
鸭子类型的概念
之前我们已经讨论过Python是一种动态类型的语言。然而,我们可以将动态方法应用于自定义数据类型。让我们来理解下面的示例。
示例
class VisualStudio:
def execute(self):
print('Compiling')
print('Running')
print('Spell Check')
print('Convention Check')
class Desktop:
def code(self, ide):
ide.execute()
ide = VisualStudio()
desk = Desktop()
desk.code(ide)
输出:
Compiling
Running
Spell Check
Convention Check
在上面的代码中,我们创建了一个名为 VisualStudio 的类,该类具有一个 execute() 方法。在桌面类中,我们将ide作为参数传递给code()。一个 ide 是 VisualStudio 类的一个对象。我们利用ide调用了 VisualStudio 类的 execute() 方法。
看看另一个示例。
示例2
class Duck:
def swim(self):
print("I'm a duck, and I can swim.")
class Sparrow:
def swim(self):
print("I'm a sparrow, and I can swim.")
class Crocodile:
def swim_walk(self):
print("I'm a Crocodile, and I can swim, but not quack.")
def duck_testing(animal):
animal.swim()
duck_testing(Duck())
duck_testing(Sparrow())
duck_testing(Crocodile())
输出:
I'm a duck, and I can swim.
I'm a sparrow, and I can swim.
Traceback (most recent call last):
File "<string>", line 24, in <module>
File "<string>", line 19, in duck_testing
AttributeError: 'Crocodile' object has no attribute 'swim'
在上面的代码中,通过调用 duck_testing 函数来映射Duck类的实例。Sparrow类也是如此,它实现了 swim() 函数。但是在鳄鱼类的情况下,它无法通过鸭子测试评估,因为它没有实现 swim() 函数。
鸭子类型如何支持EAFP
鸭子类型是最适合EAFP的编码风格,因为我们不需要关注对象的 “类型” ,我们只需要关注其 行为 和 能力 。让我们看看以下陈述。
当我们看到很多if-else代码块时,这是LBYL编码风格。
但是,如果我们看到很多try-except代码块,则很可能是EAFP的编码者。