python 基础知识 | 变量的作用域

命名空间和作用域

命名空间

命名空间提供了在项目中避免名字冲突的一种方法。各个命名空间是独立的,没有任何关系的,所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响。

# 内置命名空间 
#   Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等。
# 全局命名空间
#   模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
# 局部命名空间
#   函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量。(类中定义的也是)

作用域

既然有了命名空间,就有了作用域,python 3中有四种作用域,检索顺序是从上到下,即Golal是无法访问Local变量的,local可以访问Glocal的变量,但是无法直接访问,需要一些处理,后面根据代码详细的列出来了各种情况。

# Local
#   最内层,包含局部变量,比如一个函数/方法内部。
# Enclosing
#   包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
# Global
#   当前脚本的最外层,比如当前模块的全局变量。
# Built-in
#   包含了内建的变量/关键字等。最后被搜索

内建作用域,是定义在builtins模块中的变量,可以通过dir命名进行查看

>>> import builtins
>>> 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']

注意:Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的。

变量

如下,在一个模块(文件)中定义了3个同名变量,

# 全局变量
var=5
def some_func():

    # 局部变量
    var=6
    def some_func1():

        #内嵌的局部变量
        var=7
        print('内嵌的局部变量:',var)
    some_func1()
    print('局部变量:',var)
some_func()
print('全局变量:',var)

结果如下:

内嵌的局部变量: 7
局部变量: 6
全局变量: 5

各命令空间内的同名变量并未相互影响

嵌套函数内引用外部函数变量

基于上面的代码,如果在函数some_func1中直接使用外部函数some_func中的var变量,结果如下:

>>> def some_func():
... 	var=6
... 	def some_func1():
... 		var+=1
... 		print('内嵌的局部变量:',var)
... 	some_func1()
... 	print('局部变量:',var)
... 
>>> some_func()
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
  File "<interactive input>", line 6, in some_func
  File "<interactive input>", line 4, in some_func1
UnboundLocalError: local variable 'var' referenced before assignment

在函数some_func1中直接使用外部函数some_func中的var变量报错,“局部变量‘var’被赋值之前被引用了”。因为在嵌套函数内部var变量使用前没有赋值,如果想直接使用外部变量var,需要通过nonlocal关键字修饰,表明该变量不是本方法的局部变量,如下:

>>> def some_func():
... 	var=6
... 	def some_func1():
... 		nonlocal var
... 		var+=1
... 		print('内嵌的局部变量:',var)
... 	some_func1()
... 	print('局部变量:',var)
... 	
>>> some_func()
内嵌的局部变量: 7
局部变量: 7
>>> print('全局变量:',var)
全局变量: 5

函数内引用全局变量

基于上面的代码,如果在函数some_func中直接使用全局变量var,结果如下:

>>> def some_func():
... 	var+=1
... 	def some_func1():
... 		var=7
... 		print('内嵌的局部变量:',var)
... 	some_func1()
... 	print('局部变量:',var)
... 
>>> some_func()
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
  File "<interactive input>", line 2, in some_func
UnboundLocalError: local variable 'var' referenced before assignment

在函数some_func中直接使用全局变量var报错,“局部变量‘var’被赋值之前被引用了”。因为在函数内部var变量使用前没有赋值,如果想直接使用全局变量var,需要通过glocal关键字修饰,表明该变量是全局变量,如下:

>>> def some_func():
... 	global var
... 	var+=1
... 	def some_func1():
... 		var=7
... 		print('内嵌的局部变量:',var)
... 	some_func1()
... 	print('局部变量:',var)
... 	
>>> some_func()
内嵌的局部变量: 7
局部变量: 6
>>> print('全局变量:',var)
全局变量: 6
发布了48 篇原创文章 · 获赞 14 · 访问量 2万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览