Python 中的命名空间和作用域是什么?2024年8月29日 | 阅读 10 分钟 在一个满是学生的教室里,至少有两名学生同名的可能性很高。我们如何称呼这些学生?我们会使用姓氏或别名来唯一识别每个人。在 Python 的对象教室中,需要个体身份。面对大量对象,Python 使用命名空间的概念来管理名称。在本教程中,我们将学习“命名空间”的含义以及更多概念,并附带示例。 Python 中的对象可以是任何东西,从变量到方法。Python 将所有对象的名称以字典的形式存储,其中名称作为键,对象作为值。 Dict = {名称1: 对象1, 名称2: 对象2…} 命名空间的定义Python 中的命名空间是定义的对象及其名称的集合,以字典的形式定义。命名空间中的每个名称:对象(键:值)对都解释了一个对应的对象。 Python 有许多内置库,因此也有许多内置对象。要检查 Python 中的所有内置对象
输出 ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
Python 使用命名空间来识别对象。它如何识别两个同名的对象? 首先,Python 中有 3 种类型的命名空间
顾名思义
请看以下示例
请注意,在单个命名空间中,不能存在两个同名的同类型对象。在不同的命名空间中可以存在同名同类型的对象。因此,一个对象可以同时存在于多个命名空间中。 这里又有一个问题当同名对象存在于多个命名空间中时,Python 如何找出我们指的是哪个对象? 答案在于一个叫做“作用域”的概念。 对象的范围是程序中它具有意义的部分。根据对象的定义位置和引用位置,解释器确定对象的范围。 当我们在程序中引用一个对象来查找它时,Python 遵循一个名为 LEGB 规则 L: 局部命名空间 E: 外层命名空间 G: 全局命名空间 B: 内置命名空间 假设我们引用了一个变量 a
以下是一些示例 示例 1 输出 object 理解在上面的程序中,我们在 enclosed_function() 内部引用 a。 命名空间
搜索将如下进行
示例 2 输出 Local object 理解 我们在 enclosed_function() 内部引用了 a 命名空间
搜索过程如下 1. L: 内层命名空间:找到 解释器打印内层命名空间中 a 的值,不再继续搜索。 示例 3 输出 enclosing 理解 我们在 enclosed_function() 内部引用了 a 命名空间
搜索过程如下 L: 内层命名空间:未找到 E: 外层命名空间:找到 示例 4 输出 NameError: name 'a' is not defined 理解 我们在 enclosing_function() 内部引用了 a 命名空间
搜索过程如下 L: 外层命名空间:未找到 E: 无外层函数 G: 未找到 B: 未找到 因此,NameError
既然我们了解了命名空间的类型,这里有一点需要注意
访问命名空间 我们之前已经在教程中使用了 dir(__builtins__) 访问了内置命名空间。现在我们将学习如何访问全局和局部命名空间 全局命名空间 我们可以使用名为 globals() 的内置函数访问全局命名空间 在交互模式 (cmd) 中 输出 {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': 理解 'a' : '全局' 这里,a 是名称,'全局' 是对象。 我们也可以在 IDE 中使用该函数 -> print(globals()) 这里是另一个例子 输出 {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': 理解 我们创建了一个函数 f(),并在其中定义了一个局部变量 b。当我们调用 globals() 时
根据您的应用程序,字典可以有不同的名称。由于它是一个字典,我们可以执行一些操作,例如
局部命名空间 与全局命名空间的 globals() 类似,有一个 locals() 函数用于访问局部命名空间。它应该在函数内部调用以获取函数的命名空间。如果它在函数外部使用,则它将表现得像 globals()。 这里有一个例子 输出 {'b': 1, 'c': 2} 3 一些重要的点需要掌握
这里有一个例子 输出 {'a': 3, 'b': 4} {'a': 5, 'b': 4} {'a': 3, 'b': 4, 'local': {...}} 理解 在上面的示例中,我们创建了一个函数 add()。Python 为函数 add() 创建了一个局部命名空间。我们将 locals() 字典存储在局部变量中。我们修改了局部变量。请注意,更改并未反映在原始局部命名空间中,我们局部创建的副本已添加到局部命名空间中。因此,我们无法像修改全局命名空间那样修改原始局部命名空间。 修改 我们了解到,两个同名对象可以存在于不同的作用域中。现在,我们将看到哪些参数可以在哪些作用域中修改,哪些不能。 这里有两个重要的点
让我们通过一个例子来理解第一点 字符串是不可变的。我们在全局作用域中定义了一个字符串 a,并在函数 f() 内部尝试修改 a 的值。因此,打印的是全局作用域中 a 的值。 可变对象 列表是可变的。因此,它在局部作用域中被修改。 如果我们尝试重新分配一个可变对象 当我们在局部作用域中重新赋值 a 时,将创建一个新的局部对象,因为两个同名对象可以存储在两个不同的命名空间中。因此,当我们在全局命名空间中引用 a 时,打印的是全局命名空间中的 a。 Python 从不让我们束手无策。如果我们需要在另一个作用域中修改不可变对象:
1. global 声明 假设我们想在函数(局部作用域)内部修改一个全局对象。为了阻止 Python 创建新的局部对象,我们可以使用 global 引用来引用全局对象 通过语句 global a,我们告诉解释器,函数内部对 a 的任何引用实际上都是对全局对象 a 的引用。 如果引用一个甚至不在全局命名空间中的全局对象会怎样?是的,Python 会创建该对象并将其放置在全局命名空间中。 2. globals() 函数 使用此函数,我们可以访问全局命名空间并更新对象 3. nonlocal 声明 如果我们要修改内层函数中外部函数的对象,可以使用 nonlocal 声明。全局声明或函数在这里不起作用,因为我们要修改的对象不在全局命名空间中,而是在外部函数的命名空间中。 这里有一个例子
结束清单
下一个主题更新 Pyspark 数据帧元数据 |
我们请求您订阅我们的新闻通讯以获取最新更新。