本系列文章译自Python之父 Guido van Rossum 的系列博客“The History of Python”。这个博客系列对我们理解Python及其演变很有帮助,经Guido同意,在这里翻译推荐给大家,希望大家喜欢,也请大家多多指教!
系列地址:http://blog.kantli.com/theme/1
1. 缘起
最近,有人通过邮件向我提了一个有趣的问题:
关键字与字面量的区别何在?为什么 Python 3 中的 True 和 False 是关键字,而不是字面量?我前段时间惊恐地发现,在 Python 2 中,我们可以给 True/False 赋值。
于是我研究了下,发现在 PEP 285 中,True、False 与 None 一样,都是常量(constants)。Python 2.4 之后,禁止用户给 None 赋值,但在 Python 3 之前,对 True/False 的赋值一直是被允许的。
是有什么特殊原因,让 None 一开始就作为变量而不是字面量吗?
2. 关键字 VS 字面量
先来回答第一个问题:关键字与字面量的区别。
在编程句法中,关键字也叫保留字,类似于这门语言中的识别器,或者从解析器的角度看,就像某种 token。识别器由字母、数字及下划线组成,但不能以数字开头(这是 Python 中的定义,其它语言,如 C和 Java 的定义也类似)。
关于关键字,最重要的一点是,它们不可以用作变量名称(方法名、类名等等)。大家比较熟悉的 Python 关键字包括 if、while、for、and、or 等等。
而字面量是一个常量的值的表示,常见的字面量包括数字(如 42,3.14,1.6e-10 等)和字符串(如 “Hello, world”)。解析器可以识别字面量,但识别的具体规则一般会很复杂。比如在 Python 3 中,以下都是数字字面量:
1231.01..01e10.1e+42123.456e-1000xfffe0o755
而以下则不是:
. # 点e10 # 识别器0y12 # 字面量 0 加一个识别器 y120xffe+10 # 字面量 0xffe 加一个加号以及数字 10
注意,字面量并不是常量。我们经常在代码中定义常量,如:
MAX_LEVELS = 15
这里,15 是字面量,而 MAX_LEVEL 则是一个识别器,由于全部都是大写字母,因此,用户可能不会在代码中改变其值,也就是说,可能是一个常量——不过,常量中使用大写字母只是惯例而已,Python 解析器并不会因为变量名由大写字母组成就把它当做常量,也不强制所有常量都用大写字母表示。
但反过来写就会被解析器拒绝:
15 = MAX_LEVELS
因为赋值操作符(=)的左边必须是一个变量,而字面量不可以作为变量名。(变量的准确定义非常复杂,有些看着像表达式的,其实也是变量,比如 d[k],(a, b),foo.bar 等等——不过 f(),() 或 42 就不是变量。在 del 语句中,也使用同样的变量定义。)
3. 解析方式
接下来,我们看 None,True 和 False。
先来看 None,因为它在语言诞生之初就有了。(相对来说,True 和 False 是后期添加的,最初是在 Python 2.2.1 版本。)None 是一个单例对象(即语言中只有一个 None),表示值的缺失。例如,假设 d 是一个字典,如果 d 中有键 k 的话,d.get(k) 会返回 d[k] ,否则就返回 None。
早期版本中,None 只是 Python 的一个“内置名称”,解析器并不知道什么 None,正如它也不知道 int,float,str 等内置类型,或 KeyError 、 ZeroDivisionError 等内置异常。所有这些,对解析器而言都是识别器,在解析用户代码时,查找它们的过程与查找其它名称的过程是一样的(比如用户自己定义的方法或变量)。
在以下代码中,每一行都是同样解析,产生一样的解析树( = ):
x = Nonex = intx = foobar
而下面的代码则会产生另一种解析树( = ):
x = 42x = 'hello'
因为解析器处理数字、字符串等字面量的方式与处理识别器的方式不同。
结合这个例子与之前 MAX_LEVEL 的例子,我们知道,如果左右互换,前面三行代码是可以被解析器接受的( = ),而后面两行则不行( = 不成立)。
4. 内置名称 VS 关键字
这样设计的结果是:如果你想恶心使用你代码的人,可以给内置变量重新赋值,比如:
int = floatdef parse_string(s): return int(s)print(parse_string('42')) # 将打印42.0
有些人可能会说:“这有什么大不了的?正常程序员肯定不会这样写。”而另一些人则完全目瞪口呆:“怎么可能有这种允许赋值给内置名称的傻逼语言?!”
这个问题比较微妙,与一致性的保持和语言的发展历史有关。我相信,如果不查文档,你肯定写不出 Python 中的所有内置名称(至少我做不到),而且我也相信,很多人并不认识每一个内置名称。(想尝试的话,可以用 dir(builtins) 命令)
就以比较奇怪的内置名称 copyright、credits 与 license为例,由于它们的存在,Python 才能在每次打开交互窗口时发出问候语:
Python 3.4.0a4+ (default:0917f6c62c62, Oct 22 2013, 10:55:35)[GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.28)] on darwinType "help