4.5 KiB
Python 中的鸭子打字
Duck typing 是动态编程的一种变体,它使用一种溯因推理的形式进行类型检查。在本文中,我们将重点关注 duck 类型化的主要直觉和 python 中 duck 类型化的例子。
Python 中的鸭子打字是什么?–溯因推理
鸭子这个词可以说来自一个流行短语:
“如果它走路像鸭子,叫起来像鸭子,那它很可能是只鸭子。”
这个短语最重要的方面是,我们实际上不知道这个物体是不是一只鸭子,我们从一系列行为中推断/推断这个物体是一只鸭子。重要的是要注意,我们不是在内部检查两个对象是否相同,而是使用已知的外部行为来匹配这两个对象。
这种推理可以转移到计算机科学领域。在动态语言中,没有显式的类型检查。但是对于某些用例来说,为了确保函数正确运行,必须验证输入类型变得很重要。这可能会导致动态类型方面的各种限制和设计问题,因此引入了 Duck 类型。
Duck typing 更重视对象内部定义的方法(行为),而不是对象本身。如果对象具有所需的方法,则允许对象通过。让我们看一个例子来理解这个概念。
鸭子打字的例子
我们定义了三个代表不同动物的类,一只鸭子,一只鹅和一只猫。它们都发出不同的声音。鸭子和鹅嘎嘎叫,而猫发出喵喵的声音。然后我们定义一个函数quak(),它接收一只动物,并用叫声打印出描述。很明显,一个没有*嘎嘎()*方法的动物,在通过函数时会给出一个错误,表示变量类型错误(表示它没有通过鸭子测试)。
# Define the three classes
class Duck:
def quack(self):
print("I am a duck and I quack.")
class Goose:
def quack(self):
print("I am a goose and I quack.")
class Cat:
def meow(self):
print("I am a dog and I meow.")
# Define the method
def quack(animal):
animal.quack()
我们经过这三只动物,让它们都呱呱地叫起来。当鸭子和鹅嘎嘎叫时,猫不会嘎嘎叫,因此抛出一个错误。
quack(Duck())
quack(Goose())
quack(Cat())
Quack Error
因此,我们看到,即使没有对象类型的外部检查,python 也通过检查方法兼容性知道该对象不支持该函数。
鸭子打字的实际例子
鸭子类型最常用的例子之一是 python 中的迭代。你有没有想过如何在 python 中用每一个 iterable 写一个 for 循环?或者事实上是什么使得一个对象是可迭代的?循环可以用于列表、 numpy 数组、生成器函数、Tensorflow/PyTorch 数据加载器等。
鸭子打字在这里发挥了作用。无论这些对象在应用方面有多么不同,都因为鸭式打字而被一视同仁。
对于迭代,该类必须有 iter() 和 next()函数,这使它有资格进行迭代。Python 没有对这些类进行强类型检查,这使得它越来越灵活。
我们甚至可以定义自己的迭代器来打印平方数,这里我们定义了方法 iter() 和 next() ,这是 python 迭代期间调用的两个方法。
class Squares:
def __init__(self, l=0, u=-1):
self.u = u
self.n = l
def __iter__(self):
return self
def __next__(self):
if self.n < self.u:
s = self.n ** 2
self.n += 1
return s
else:
raise StopIteration
for i in Squares(1, 4):
print(i)
1
4
9
结论
python 中对 duck typing 的支持实现了基本 Python 函数与用户定义的类的无缝集成。这也允许两个不同类之间的交互和集成。我们已经看到了 python 中迭代器的一个例子,这个概念可以应用到 len() 中,它检查对象内部是否定义了 len()方法。您可以在 python 中尝试各种其他方法,探索 python 到底有多灵活。
