第 17 章 范围 范围
本作品已使用人工智能进行翻译。欢迎您提供反馈和意见:translation-feedback@oreilly.com
第 16 章介绍了基本的函数定义和调用。正如我们所看到的,Python 的核心函数模型简单易用,但即使是简单的函数示例也会很快让我们对代码中变量的含义产生疑问。本章将继续介绍 Python 的作用域--变量定义和查找的地方--背后的细节。与模块文件一样,作用域有助于防止程序代码中的名称冲突:一个程序单元中定义的名称不会与另一个单元中的名称冲突。
我们将看到,在代码中分配名称的位置对于确定名称的含义至关重要。我们还将发现,作用域的使用会对程序维护工作产生重大影响;例如,过度使用全局一般都是一件坏事。从好的方面来看,我们将了解到作用域可以在函数调用之间提供一种保留状态信息的方法,并在某些情况下提供了类的替代品。
Python 范围基础知识
现在您已经准备好开始编写自己的函数了,我们需要更正式地了解 Python 中名称的含义。当您在程序中使用名称时,Python 会创建、更改或在所称的名称空间(namespace)中查找名称--名称所在的地方。当我们谈论搜索与代码相关的名称值时,术语scope指的是名称空间:也就是说,名称在源代码中的赋值位置决定了名称在代码中的可见范围。
在 Python 中,几乎所有与名称相关的事情,包括作用域分类,都是在赋值时发生的。正如我们所看到的,Python 中的名字是在第一次赋值时 Spring 出现的,它们必须在使用之前被赋值。由于名称没有提前声明,Python 使用名称赋值的位置将其与特定的名称空间关联(即绑定到)。换句话说,在源代码中赋值名称的位置决定了它所处的命名空间,也就决定了它的可见范围。
除了打包代码以便重复使用外,函数还为程序添加了一个额外的命名空间层,以尽量减少同名变量之间发生碰撞的可能性--默认情况下,函数内部分配的所有名称都与该函数的命名空间相关联,而不是其他命名空间。这一规则意味着
在
def中分配的名称只能被def中的代码看到。您甚至不能从函数外部引用这些名称。在
def内分配的名称不会与def外的变量发生冲突,即使其他地方也使用了相同的名称。在给定的def(即在不同的def或模块文件的顶层)之外分配的名称X与在该def内部分配的名称X是完全不同的变量。
在任何情况下,变量的作用域(可以在哪里使用)总是由它在源代码中的赋值位置决定的,与调用哪个函数无关。事实上,正如我们将在本章学到的,变量可能被分配到三个不同的地方,对应三个不同的作用域:
如果一个变量被分配到
def中,它就是该函数的局部变量。如果变量是在外层
def中赋值的,则它对嵌套函数来说是非本地变量。如果一个变量被赋值到所有
defs 之外,那么它就是整个文件的全局变量。
我们将这种词法作用域称为,因为变量作用域完全由程序文件源代码中的变量位置决定,而不是由函数调用决定。
例如,在下面的模块文件中,X = 99 赋值会创建一个名为X 的全局变量(在该文件中随处可见),但X = 88 赋值会创建一个局部变量 X(仅在def语句中可见):
X = 99# Global (module) scope Xdef func(): X = 88# Local (function) scope X: a different variable
尽管这两个变量都被命名为X ,但它们的作用域是不同的。这样做的净效果是,函数作用域有助于避免程序中的名称冲突,并有助于使函数成为更独立的程序单元--它们的代码不必关心其他地方使用的名称。 ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access