Python 遵循 EAFP(取得原谅比获得许可容易)哲学,而不是 LBYL(三思而后行)哲学。Python 的 EAFP 哲学在某种程度上与其“鸭子类型”编码风格相关联。
当程序员在代码中创建数据时,无论是常量还是变量,一些编程语言需要知道数据的“类型”。例如,如果您将变量设置为 13,计算机不知道您是想将其用作单词(“thirteen”)还是整数(如 13+12=25 或 13-1=12)。这就是为什么许多语言要求程序员在使用数据之前声明数据。
例如,在以下 C++ 代码中,mynumber 变量是整数类型,而 myword 变量是字符串
#include <iostream>
#include <string>
using namespace std;
int mynumber = 13;
string myword = "13";
int main() {
std::cout << 13+2 << endl;
std::cout << "My favourite number is " + myword << endl;
}
然而,Python 很聪明,它使用“鸭子测试”:如果一个变量走起来像鸭子,叫起来像鸭子,那么它就是鸭子。换句话说,应用于计算机科学,这意味着 Python 检查数据以确定其类型。Python 知道整数用于数学运算,单词用于通信,因此程序员不必向 Python 解释如何使用在变量中找到的数据。Python 使用鸭子类型来自行弄清楚,并且不会尝试对字符串进行数学运算或打印数组的内容(没有迭代),等等。
但是,在我们讨论这些概念之前,让我们先回顾一下基础知识
理解“类型”概念的类比
“类型”的概念在编程语言的上下文中经常被讨论,但通常,更深层的含义却被我们忽略了。所以,让我尝试用一个类比来解释这个概念。
在计算机程序中,对象和其他项目存储在内存中,并且通常由某些“变量名”引用。因此,当您创建特定类的对象时(在任何流行的编程语言中),您基本上是在为该对象保留一部分内存以供占用,然后您使用该变量名引用该对象。
因此,作为一个类比,您可以将内存中的这个空间视为一种容器或盒子。为了这个练习,我们称之为盒子。所以现在我们有两样东西——一个对象和一个包含它的盒子。
为了进一步论证,通常,盒子必须“设计”成能够容纳它所包含的对象(即,用于装火柴的盒子不适合装鞋子,反之亦然,即使物理上是可能的)。所以,我们可以同意对象和包含它的盒子都必须是相似的类型吗?
事实上,这就是所谓的“静态类型”。基本上,这意味着不仅对象必须具有“类型”,而且变量名(又名盒子)也必须具有类型,并且它应该是相同或相似的。(我稍后会解释为什么我说“相似”)。这就是为什么在 Java/C++ 等静态类型语言中,您需要在创建变量时定义变量的类型。事实上,您可以创建一个类似于盒子的变量名,即使不创建任何对象来放入其中。您不能在 Python 中这样做。
然而,像 Python 这样的动态类型语言的工作方式不同。在这里,您可以将变量名视为不像盒子,而更像“标签”(有点像商店里的价格标签)。因此,标签没有类型。相反,如果您询问标签的类型,它可能会选择此时此刻它所标记的对象。我说“此时此刻”是因为,就像在现实世界中一样,附在鞋子上的标签也可能在不同的时间附在其他物品上。因此,Python 解释器本身不会为变量名分配任何类型。但是,如果您询问变量名的类型,那么它会给出当前与其绑定的对象的类型。这就是动态类型。
这种动态类型与静态类型的对比直接影响您编写代码的方式。就像在现实世界中,您不能将鞋子放入装火柴的盒子中一样,在静态类型语言中也是如此——您通常不能将一种类型的对象放入为另一种类型的对象创建的变量名中。
强类型语言与弱类型语言
这里还有另一个重要的概念需要讨论,即强类型语言和弱类型语言。“类型强度”实际上与它是动态类型还是静态类型无关。它更多地与“类型转换”或将一种类型的对象转换为另一种类型的能力有关。与流行的看法相反,Python 是一种相当强类型的语言,就像 C++ 或 Java 一样。因此,例如,在 Python 中,您不能将“整数”添加到“字符串”,但是,您可以在像 JavaScript 这样的语言中做到这一点。事实上,JavaScript 是臭名昭著的“弱类型”语言之一。因此,应该清楚的是,强/弱类型是与静态/动态类型完全不同的尺度。一般来说,像 Python 这样的脚本语言倾向于动态类型,而编译语言倾向于静态类型。
鸭子类型、EAFP 和 LBYL
Python 遵循鸭子类型编码风格。
让我们再次举一个现实世界的例子。假设您有一个对象“机器 M”。现在,您不知道这台机器 M 是否具有飞行能力。下图说明了 LBYL 与 EAFP 的处理方式

让我们用一些 Python 代码(使用虚构的函数)来阐明这个概念
# LBYL:- Look Before You Leap
if can_fly():
fly()
else:
do_something_else()
# EAFP:- Easier to Ask Forgiveness than permission
try:
fly()
except:
clean_up()
鸭子类型如何支持 EAFP
鸭子类型非常适合 EAFP 编码风格。这是因为我们不关心对象的“类型”;我们只关心它的“行为”和“能力”。“行为”我基本上指的是它的属性,“能力”我指的是它的方法。
总结
如果您看到很多 if-else
块,那么您就是 LBYL 程序员。
但是,如果您看到很多 try-except
块,您可能就是 EAFP 程序员。
9 条评论