【Python】作用域

265 阅读2分钟

作用域

python仅有LEGB四种作用域,意味着if/elsewhile等语句不会产生新的作用域

  1. LEGB
    • L:Local
    • E:Enclosing
    • G:Global
    • B:Builtin

四种作用域相关

globalVar = 1  # G for any,L for module

def func():
    funcLocalVar = 2  # E for inner() below, L for func()

    def inner():
        innerLocalVar = 3  # L for inner()

print __name__  # B
  1. 对于LEGB,仅有当变量在该域内的作用域类型为L时才可进行读写; 对于其他类型都是仅可读,每次尝试写入都是新声明 = Declare on Write

G <Global> 相关说明

代码:
# Declare a globalVar
globalVar = 1  # G for any,L for module


def globalFunc():
    globalVar = 2  # Try to write globalVar. 
    print globalVar  # output: 2


# globalFunc() trying to write globalVar
globalFunc()
# Print globalVar in module
print globalVar  # output: 1. Means that the globalVar hasn't been written.
# Write globalVar in module.
globalVar = 3
# Print globalVar in module
print globalVar  # output: 3. Means that the globalVar has been written.

# Noticed that globalVar in module is G for globalFunc(), so writing in globalFunc equals declaring.
# And after declaring, globalVar now is L for globalFunc

结论:

  • 全局globalVar对于globalFunc而言作用域类型是为G,故在globalFunc内进行写入视为声明
  • 而在声明后,方法内部的globalVar成为局部变量,独立于全局版本

E <Enclosing> 相关说明

代码:
# Keeping same with Global
def enclosingFunc():
    funcLocalVar = 1  # E for inner() below, L for enclosingFunc()

    def inner():
        funcLocalVar = 2  # Try to write funcLocalVar.
        print funcLocalVar  # output: 2

    # inner() trying to write funcLocalVar
    inner()
    print funcLocalVar  # output: 1. Means that the globalVar hasn't been written.
    # etc...


enclosingFunc()
# Statements keep with Global

结论:

  • 结论与Global基本一致,可类推,不赘述。
  1. 想要修改其他类型的变量时,使用global/nonlocal等修饰符引入变量
    • global = 修改Global
    • nonlocal = 修改Enclosing [python3.x]

Global举例代码

# Declare a globalVar
globalVar = 1  # G for any,L for module

def globalFunc1():
    global globalVar  # G for globalFunc1. Use global will declare globalVar to this method.
    globalVar = 2  # Try to write globalVar. We can actually write for it's declared.
    print globalVar  # output: 2

# globalFunc() trying to write globalVar
globalFunc()
# Print globalVar in module
print globalVar  # output: 2. Means that the globalVar has been written.
  1. QA
  • 问:如果希望在python2.x中达到nonlocal的效果,有什么方法吗? 答:无官方支持,但实现上可以在闭包将要使用的对象上使用一层对象或者词典进行包装。如:
# Declare DataWrapper to wrap our enclosing data.
class DataWrapper(object):
    def __init__(self, var):
        self.var = var

# Keeping same with Global
def enclosingFunc():
    funcLocal = DataWrapper(1)  # Declare funcLocal as DataWrapper, and take our data as DataWrapper field.

    def inner():
        funcLocal.var = 2  # Try to write funcLocal.var.
        print funcLocal.var  # output: 2

    # inner() trying to write funcLocalVar
    inner()
    print funcLocal.var  # output: 2. Means that the funcLocal.var has been written.

enclosingFunc()