geekdoc-python-zh/docs/askpython/duck-typing.md

106 lines
4.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Python 中的鸭子打字
> 原文:<https://www.askpython.com/python/oops/duck-typing>
Duck typing 是动态编程的一种变体,它使用一种溯因推理的形式进行[类型检查](https://www.askpython.com/python/built-in-methods/python-type-function)。在本文中,我们将重点关注 duck 类型化的主要直觉和 python 中 duck 类型化的例子。
## Python 中的鸭子打字是什么?–溯因推理
鸭子这个词可以说来自一个流行短语:
“如果它走路像鸭子,叫起来像鸭子,那它很可能是只鸭子。”
这个短语最重要的方面是,我们实际上不知道这个物体是不是一只鸭子,我们从一系列行为中推断/推断这个物体是一只鸭子。重要的是要注意,我们不是在内部检查两个对象是否相同,而是使用已知的外部行为来匹配这两个对象。
这种推理可以转移到计算机科学领域。在动态语言中,没有显式的类型检查。但是对于某些用例来说,为了确保函数正确运行,必须验证输入类型变得很重要。这可能会导致动态类型方面的各种限制和设计问题,因此引入了 Duck 类型。
Duck typing 更重视对象内部定义的方法(行为),而不是对象本身。如果对象具有所需的方法,则允许对象通过。让我们看一个例子来理解这个概念。
## 鸭子打字的例子
我们定义了三个代表不同动物的类,一只鸭子,一只鹅和一只猫。它们都发出不同的声音。鸭子和鹅嘎嘎叫,而猫发出喵喵的声音。然后我们定义一个函数*quak()*,它接收一只动物,并用叫声打印出描述。很明显,一个没有*嘎嘎()*方法的动物,在通过函数时会给出一个错误,表示变量类型错误(表示它没有通过鸭子测试)。
```py
# 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()
```
我们经过这三只动物,让它们都呱呱地叫起来。当鸭子和鹅嘎嘎叫时,猫不会嘎嘎叫,因此抛出一个错误。
```py
quack(Duck())
quack(Goose())
quack(Cat())
```
![Quack Error - duck typing in Python](img/303fffdff1b4e34b9435c179b43c8543.png)
Quack Error
因此我们看到即使没有对象类型的外部检查python 也通过检查方法兼容性知道该对象不支持该函数。
## 鸭子打字的实际例子
鸭子类型最常用的例子之一是 python 中的迭代。你有没有想过如何在 python 中用每一个 iterable 写一个 [for 循环](https://www.askpython.com/python/python-for-loop)?或者事实上是什么使得一个对象是可迭代的?循环可以用于列表、 [numpy 数组](https://www.askpython.com/python-modules/numpy/python-numpy-arrays)、[生成器函数](https://www.askpython.com/python/examples/generators-in-python)、Tensorflow/PyTorch 数据加载器等。
鸭子打字在这里发挥了作用。无论这些对象在应用方面有多么不同,都因为鸭式打字而被一视同仁。
对于迭代,该类必须有 *[__iter__()](https://www.askpython.com/python/python-iter-function)*__next__()函数这使它有资格进行迭代。Python 没有对这些类进行强类型检查,这使得它越来越灵活。
我们甚至可以定义自己的迭代器来打印平方数,这里我们定义了方法 *__iter__()**__next__()* ,这是 python 迭代期间调用的两个方法。
```py
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
```
```py
for i in Squares(1, 4):
print(i)
```
```py
1
4
9
```
## 结论
python 中对 duck typing 的支持实现了基本 Python 函数与用户定义的类的无缝集成。这也允许两个不同类之间的交互和集成。我们已经看到了 python 中迭代器的一个例子,这个概念可以应用到 [len()](https://www.askpython.com/python/string/find-string-length-in-python) 中,它检查对象内部是否定义了 __len__()方法。您可以在 python 中尝试各种其他方法,探索 python 到底有多灵活。
### 参考
* [崔永的中型文章](https://medium.com/swlh/duck-typing-in-python-3-practical-examples-a40d8113266c)
* [开源文章](https://opensource.com/article/20/5/duck-typing-python)