"""
Python3 命名空间和作用域。
模块:python3 namespace_scope 命名空间和作用域.py
参考:https://www.runoob.com/python3/python3-namespace-scope.html
知识点:
1.命名空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的。
2.一般有三种命名空间:
内置名称(built-in names), Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等。
全局名称(global names),模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
局部名称(local names),函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量。(类中定义的也是)
3.命名空间查找顺序:
假设我们要使用变量 runoob,则 Python 的查找顺序为:局部的命名空间去 -> 全局命名空间 -> 内置命名空间。
如果找不到变量 runoob,它将放弃查找并引发一个 NameError 异常:
NameError: name 'runoob' is not defined。
4.命名空间的生命周期:
命名空间的生命周期取决于对象的作用域,如果对象执行完成,则该命名空间的生命周期就结束。
因此,我们无法从外部命名空间访问内部命名空间的对象。
5.Python 的作用域一共有 4 种,分别是:
L(Local):最内层,包含局部变量,比如一个函数/方法内部。
E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。
比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,
那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
G(Global):当前脚本的最外层,比如当前模块的全局变量。
B(Built-in):包含了内建的变量/关键字等,最后被搜索。
规则顺序: L –> E –> G –> B。
在局部找不到,便会自动去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。
6.在局部作用域,想要访问(CRUD)全局作用域、包围作用域的变量有 3 种方式:
1.传参。
2.使用 global var(提前声明,访问全局作用域), nonlocal var(提前声明,访问紧挨着的包围作用域)。
3.在当前作用域中,没有该变量,会自动、顺序地去更大的域中寻找,直到找到。
或者,报错 NameError: name 'var' is not defined。
这种情况下,不可变类型,比如:字符串,数字,元组,可读,不可改变
(提前使用 global, nonlocal 声明,这种情况可以解除)。
可变类型,如:列表,字典,集合,可读,可改。
7.
"""
import builtins
import pprint
# 1.查看 内建变量。
# help(builtins)
# pprint.pprint(dir(builtins))
# print(dir(builtins))
# ['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']
# 2.全局变量。
var1 = 5
def some_func():
# 3.包围变量(Enclosing)。
var2 = 6
def some_inner_func():
# 4.局部变量。
var3 = 7
# 5.Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,
# 其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,
# 也就是说这些语句内定义的变量,外部也可以访问。
if True:
msg = 'I am from Runoob.'
print("\n5.")
print(msg) # I am from Runoob.
# 6.全局变量和局部变量
# 定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
# 局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。
# 在函数内,访问全局变量时,需要提前声明,如:global var, var...
# 调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。如下实例:
print("\n6.")
total = 0 # 这是一个全局变量
# 函数说明
def my_sum(arg1, arg2):
"""
求两个数的和。
:param arg1:
:param arg2:
:return:
"""
total = arg1 + arg2 # total在这里是局部变量.
print("局部 total:", total)
return total
my_sum(10, 20)
print("全局 total:", total)
# 局部 total: 30
# 全局 total: 0
# 7.global 和 nonlocal关键字
# 当内部作用域访问外部作用域的变量时,就要用到 global和 nonlocal 关键字了。
num = 1
def fun1():
global num # 需要使用 global 关键字声明
print(num)
num = 123
print(num)
print("\n7.")
fun1()
print(num)
# 1
# 123
# 123
# 7.2.如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量,则需要 nonlocal 关键字了。
def outer():
num = 10
def inner():
nonlocal num # nonlocal关键字声明
num = 100
print(num)
inner()
print(num)
print("\n7.2.")
outer()
# 100
# 100
# 7.3.函数参数的绑定关系。
# 变量不是对象,变量用于绑定对象,变量和对象之间的关系称为绑定(引用)关系。
# 把数字对象 10 赋值给 a, 那么 a 就绑定(引用)了 数字对象 10。
# 函数的参数是局部变量。
a = 10
def test(a):
# a = a + 1
# a += 1
a = 1
print(a)
print(locals()) # {'a': 1}
print("\n7.3.")
test(a)
print(a)
# 1
# 10
# 8.在局部、包围、全局作用域,可以直接访问内建作用域的变量,不用提前声明。
# 以 str(), type() 内建变量为例。
print("\n8.")
n = 10
s = str(n)
print(s, type(s))
# 10 <class 'str'>
# 8.2.
def f():
n = 10
s = str(n)
print(s, type(s))
f() # 10 <class 'str'>
# 8.3.
def f():
n = 10
s = str(n)
print(s, type(s))
def f():
pass
f() # 10 <class 'str'>
# 9.在当前作用域中,没有该变量,会自动、顺序地去更大的域中寻找,直到找到。
# 或者,报错 NameError: name 'var' is not defined。
# 这种情况下,不可变类型,比如:字符串,数字,元组,可读,不可改变
# (提前使用 global, nonlocal 声明,这种情况可以解除)。
# 可变类型,如:列表,字典,集合,可读,可改。
i = 0
i += 1
# del i
list1 = [0, 1]
def fun1():
# global i # 使用 global i 声明,可以解除,不可变类型不能直接改的情况。
# i += 1 # 不能改。
# i = i + 1 # 同上
print(i) # 不可变类型,可以直接读,但是不能改,如上操作。
list1.append(i) # 可变类型,可读可改。
print(list1)
print(locals())
print("\n9.")
fun1()
print(list1)
# 1
# [0, 1, 1]
# {}
# [0, 1, 1]
python3 namespace_scope 命名空间和作用域.py
最新推荐文章于 2024-03-30 12:01:45 发布