美文网首页
python的作用域

python的作用域

作者: agamgn | 来源:发表于2020-02-16 07:21 被阅读0次

前言

 作用域是程序运行时变量可被访问的范围。

作用域

 python变量的作用域很简单,就是LEGB:变量名引用分为三个作用域进行查找,首先是本地(L),之后是函数内(F),之后是全局(G),最后是内置(B)。Python会按照优先级依次搜索4个作用域。

L(local)局部作用域

 局部变量:包含在def关键字定义的语句块中,即在函数中定义的变量。每当函数被调用时都会创建一个新的局部作用域。
 在函数内部的变量声明,除非特别的声明(后文会将),否则均默认为局部变量。

def func():
    x=1
    print(x)#1
print(x)# name 'x' is not defined
E(enclosing)嵌套作用域

 E也包含在def关键字中,E和L是相对的,E相对于更上层的函数而言也是L。与L的区别在于,对一个函数而言,L是定义在此函数内部的局部作用域,而E是定义在此函数的上一层父级函数的局部作用域。主要是为了实现Python的闭包,而增加的实现。

def func():
    x=1
    def innerfunc():
        print(x)
    innerfunc()
func()# 1
G(global)全局作用域

 即在模块层次中定义的变量,每一个模块都是一个全局作用域。也就是说,在模块文件顶层声明的变量具有全局作用域,从外部开来,模块的全局变量就是一个模块对象的属性。 注意:全局作用域的作用范围仅限于单个模块文件内。

funcnum=10
def func():
    print (funcnum)
func()#10
B(built-in)内置作用域

 系统内固定模块里定义的变量,如预定义在builtin 模块内的变量。

 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']
oct(8)
# '0o10'

实例讲解

 通过几个例子来加深对python变量作用域的理解。

demo1
def func1():
    vars=300
    print(vars)

vars=100
func1()
print(vars)
# 300
# 100

本例中,有一个全局变量vars,值为100,有一个作用域为func1函数内部的局部变量vars,值为300,func1内部输出vars变量值时,优先搜索局部作用域,所以打印输出300。

demo2
def func2():
    var2=100
    print(var2)
    def innerfunc2():
        print(var2)
    innerfunc2()
var2=200
func2()
print(var2)
# 100
# 100
# 200

 有两个var2变量,对于innerfunc2函数来说,局部作用域中没有var2变量,所以打印时,在L层找不到,所以进一步在E层找,即在上层函数func2中定义的var2,找到并输出。

demo3
var3=300
def func3():
    var3=200
func3()
print(var3)
# 300

 在局部变量中修改的不影响全局变量中的值。

修改作用域

 如果希望修改变量的作用域可以使用global、nonlocal关键字。

global关键字

 如果希望在L作用域中修改G作用域中的变量,则应该使用global关键字。

var=99
def func():
    def innerfunc():
        global var
        print("var=",var)
        var =100
    return innerfunc
func()()
print(var)
# var= 99
# 100

 上段代码中,定义了一个内部函数,并作为一个变量返回,所以func()相当于innerfunc,而不是innerfunc(),所以func()()相当于innerfunc()。这里需要注意的是global关键字,使用了这个关键字之后,在innerfunc函数中使用的var变量就是全局作用域中的var变量,而不会新生成一个局部作用域中的var变量。

nonlocal关键字

 在L作用域中修改E作用域中的变量,就需要使用nonlocal关键字了,这个是python3中新增加的特性。

def outer():
    count=10
    def inner():
        nonlocal count
        count=20
        print(count)
    inner()
    print(count)
outer()
# 20
# 20

 由于声明了nonlocal,这里inner中使用的count变量就是E即outer函数中生命的count变量,所以输出两个20。

总结

参考文章Python基本语法_变量作用域LEGB
code:本节代码

相关文章

网友评论

      本文标题:python的作用域

      本文链接:https://www.haomeiwen.com/subject/dhrhxhtx.html