Python命名空间和作用域

Python使用叫做命名空间的东西来记录变量的轨迹。命名空间是一个 key为变量名,value为变量值的字典

内置命名空间

Python内部使用的命名空间,包含内建函数名、异常类型名、内部常量名等等。
可以通过builtins模块来查看内置命名空间(下列输出经过格式化处理):

>>> import builtins
>>> builtins.__dict__
{
    '__name__': 'builtins',
    '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.",
    '__package__': '',
    '__loader__': < class '_frozen_importlib.BuiltinImporter' > ,
    '__spec__': ModuleSpec(name = 'builtins', loader = < class '_frozen_importlib.BuiltinImporter' > ),
    '__build_class__': < built - in function __build_class__ > ,
    '__import__': < built - in function __import__ > ,
    'abs': < built - in function abs > ,
    'all': < built - in function all > ,
    'any': < built - in function any > ,
    'ascii': < built - in function ascii > ,
    'bin': < built - in function bin > ,
    'breakpoint': < built - in function breakpoint > ,
    'callable': < built - in function callable > ,
    'chr': < built - in function chr > ,
    'compile': < built - in function compile > ,
    'delattr': < built - in function delattr > ,
    'dir': < built - in function dir > ,
    'divmod': < built - in function divmod > ,
    'eval': < built - in function eval > ,
    'exec': < built - in function exec > ,
    'format': < built - in function format > ,
    'getattr': < built - in function getattr > ,
    'globals': < built - in function globals > ,
    'hasattr': < built - in function hasattr > ,
    'hash': < built - in function hash > ,
    'hex': < built - in function hex > ,
    'id': < built - in function id > ,
    'input': < built - in function input > ,
    'isinstance': < built - in function isinstance > ,
    'issubclass': < built - in function issubclass > ,
    'iter': < built - in function iter > ,
    'len': < built - in function len > ,
    'locals': < built - in function locals > ,
    'max': < built - in function max > ,
    'min': < built - in function min > ,
    'next': < built - in function next > ,
    'oct': < built - in function oct > ,
    'ord': < built - in function ord > ,
    'pow': < built - in function pow > ,
    'print': < built - in function print > ,
    'repr': < built - in function repr > ,
    'round': < built - in function round > ,
    'setattr': < built - in function setattr > ,
    'sorted': < built - in function sorted > ,
    'sum': < built - in function sum > ,
    'vars': < built - in function vars > ,
    'None': None,
    'Ellipsis': Ellipsis,
    'NotImplemented': NotImplemented,
    'False': False,
    'True': True,
    'bool': < class 'bool' > ,
    'memoryview': < class 'memoryview' > ,
    'bytearray': < class 'bytearray' > ,
    'bytes': < class 'bytes' > ,
    'classmethod': < class 'classmethod' > ,
    'complex': < class 'complex' > ,
    'dict': < class 'dict' > ,
    'enumerate': < class 'enumerate' > ,
    'filter': < class 'filter' > ,
    'float': < class 'float' > ,
    'frozenset': < class 'frozenset' > ,
    'property': < class 'property' > ,
    'int': < class 'int' > ,
    'list': < class 'list' > ,
    'map': < class 'map' > ,
    'object': < class 'object' > ,
    'range': < class 'range' > ,
    'reversed': < class 'reversed' > ,
    'set': < class 'set' > ,
    'slice': < class 'slice' > ,
    'staticmethod': < class 'staticmethod' > ,
    'str': < class 'str' > ,
    'super': < class 'super' > ,
    'tuple': < class 'tuple' > ,
    'type': < class 'type' > ,
    'zip': < class 'zip' > ,
    '__debug__': True,
    'BaseException': < class 'BaseException' > ,
    'Exception': < class 'Exception' > ,
    'TypeError': < class 'TypeError' > ,
    'StopAsyncIteration': < class 'StopAsyncIteration' > ,
    'StopIteration': < class 'StopIteration' > ,
    'GeneratorExit': < class 'GeneratorExit' > ,
    'SystemExit': < class 'SystemExit' > ,
    'KeyboardInterrupt': < class 'KeyboardInterrupt' > ,
    'ImportError': < class 'ImportError' > ,
    'ModuleNotFoundError': < class 'ModuleNotFoundError' > ,
    'OSError': < class 'OSError' > ,
    'EnvironmentError': < class 'OSError' > ,
    'IOError': < class 'OSError' > ,
    'WindowsError': < class 'OSError' > ,
    'EOFError': < class 'EOFError' > ,
    'RuntimeError': < class 'RuntimeError' > ,
    'RecursionError': < class 'RecursionError' > ,
    'NotImplementedError': < class 'NotImplementedError' > ,
    'NameError': < class 'NameError' > ,
    'UnboundLocalError': < class 'UnboundLocalError' > ,
    'AttributeError': < class 'AttributeError' > ,
    'SyntaxError': < class 'SyntaxError' > ,
    'IndentationError': < class 'IndentationError' > ,
    'TabError': < class 'TabError' > ,
    'LookupError': < class 'LookupError' > ,
    'IndexError': < class 'IndexError' > ,
    'KeyError': < class 'KeyError' > ,
    'ValueError': < class 'ValueError' > ,
    'UnicodeError': < class 'UnicodeError' > ,
    'UnicodeEncodeError': < class 'UnicodeEncodeError' > ,
    'UnicodeDecodeError': < class 'UnicodeDecodeError' > ,
    'UnicodeTranslateError': < class 'UnicodeTranslateError' > ,
    'AssertionError': < class 'AssertionError' > ,
    'ArithmeticError': < class 'ArithmeticError' > ,
    'FloatingPointError': < class 'FloatingPointError' > ,
    'OverflowError': < class 'OverflowError' > ,
    'ZeroDivisionError': < class 'ZeroDivisionError' > ,
    'SystemError': < class 'SystemError' > ,
    'ReferenceError': < class 'ReferenceError' > ,
    'MemoryError': < class 'MemoryError' > ,
    'BufferError': < class 'BufferError' > ,
    'Warning': < class 'Warning' > ,
    'UserWarning': < class 'UserWarning' > ,
    'DeprecationWarning': < class 'DeprecationWarning' > ,
    'PendingDeprecationWarning': < class 'PendingDeprecationWarning' > ,
    'SyntaxWarning': < class 'SyntaxWarning' > ,
    'RuntimeWarning': < class 'RuntimeWarning' > ,
    'FutureWarning': < class 'FutureWarning' > ,
    'ImportWarning': < class 'ImportWarning' > ,
    'UnicodeWarning': < class 'UnicodeWarning' > ,
    'BytesWarning': < class 'BytesWarning' > ,
    'ResourceWarning': < class 'ResourceWarning' > ,
    'ConnectionError': < class 'ConnectionError' > ,
    'BlockingIOError': < class 'BlockingIOError' > ,
    'BrokenPipeError': < class 'BrokenPipeError' > ,
    'ChildProcessError': < class 'ChildProcessError' > ,
    'ConnectionAbortedError': < class 'ConnectionAbortedError' > ,
    'ConnectionRefusedError': < class 'ConnectionRefusedError' > ,
    'ConnectionResetError': < class 'ConnectionResetError' > ,
    'FileExistsError': < class 'FileExistsError' > ,
    'FileNotFoundError': < class 'FileNotFoundError' > ,
    'IsADirectoryError': < class 'IsADirectoryError' > ,
    'NotADirectoryError': < class 'NotADirectoryError' > ,
    'InterruptedError': < class 'InterruptedError' > ,
    'PermissionError': < class 'PermissionError' > ,
    'ProcessLookupError': < class 'ProcessLookupError' > ,
    'TimeoutError': < class 'TimeoutError' > ,
    'open': < built - in function open > ,
    'quit': Use quit() or Ctrl - Z plus Return to exit,
    'exit': Use exit() or Ctrl - Z plus Return to exit,
    'copyright': Copyright(c) 2001 - 2019 Python Software Foundation.
    All Rights Reserved.
    Copyright(c) 2000 BeOpen.com.
    All Rights Reserved.
    Copyright(c) 1995 - 2001 Corporation
    for National Research Initiatives.
    All Rights Reserved.
    Copyright(c) 1991 - 1995 Stichting Mathematisch Centrum,
    Amsterdam.
    All Rights Reserved.,
    'credits': Thanks to CWI,
    CNRI,
    BeOpen.com,
    Zope Corporation and a cast of thousands
    for supporting Python development.See www.python.org
    for more information.,
    'license': Type license() to see the full license text,
    'help': Type help() for interactive help,
    or help(object) for help about object.,
    '_': None
}

Python内置命名空间的作用域是全局的,这里的全局指的是Python内的全局,而不是某个模块的全局,在任意Python代码中都可以使用内置命名空间中的函数、类和常量,因此,其余各级命名空间中的对象在命名时,不允许出现和内置命名空间已有的名称重名。

相关文档:

  • builtins --- 内建对象 — Python 3.7.12 文档
  • 内置函数 — Python 3.7.12 文档
  • 内置常量 — Python 3.7.12 文档

全局命名空间

这里全局指的是一个模块的全局,每个.py文件都是一个Python模块,每个模块都有自己命名空间,叫做全局命名空间。
全局命名空间记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
全局命名空间作用域在模块内部,如果要在其它模块使用时,需要先导入(import)此模块,然后以.的形式调用。
可以通过内建函数globals()访问全局命名空间

局部命名空间

模块中的每个函数都是一个局部,拥有一个局部命名空间。
局部命名空间的作用域也在全局命名空间的作用域之中,并且局部命名空间可以使用全局命名空间中已有的名称。
如果需要在局部命名空间使用全局命名空间的变量,比如全局变量x,分读取和修改两种情况:

  • 读取
    在局部命名空间,如果没有创建新的变量x,则调用x时默认使用的就是全局命名空间中的x
  • 修改
    在局部命名空间,直接对x赋值,只会创建一个局部变量x。要修改全局变量x则需要先在局部命空间中使用global关键字将x声明为变量:global x,然后再对x赋值。

名称查找顺序

在函数中需要使用变量a,那查找变量a的顺序如下:
1、先查找局部命名空间有没有定义a这个局部变量参数,有则停止查询;没有则向上查找全局命名空间
2、查找全局命名空间有没有定义a这个变量函数,有则停止查询;没有则查找内置命名空间
3、内置命名空间有a这个函数变量则停止查询,否则抛出NameError异常

可以通过内建函数locals()访问局部命名空间

闭包命名空间

闭包的定义:内部函数包含对外部作用域而非全局作用域变量的引用,该内部函数称为闭包函数

函数中可以嵌套函数,嵌套函数就是闭包函数,其所在的命名空间就是闭包命名命名空间。
闭包命名空间和局部命名空间类似,只是其级别更低,作用域更小,只在嵌套函数内生效。
假设局部命名空间有变量x,在嵌套函数中可以直接对x进行读取和修改;如果需要重新创建一个同名变量,则需要先用nonlocal关键字声明:nonlocal x,再对x赋值。
在闭包函数中也可以使用使用global关键字,直接修改全局变量。

你可能感兴趣的:(Python命名空间和作用域)