Python:为什么说只引用的变量是隐式全局的?

Nio*_*urf 6 python global

Python FAQ中我们可以阅读:

在Python中,仅在函数内引用的变量是隐式全局变量

关于定义函数Python教程中,我们可以阅读:

函数的执行引入了用于函数局部变量的新符号表.更确切地说,函数中的所有变量赋值都将值存储在本地符号表中; 而变量引用首先在本地符号表中查找,然后在封闭函数的本地符号表中查找,然后在全局符号表中查找,最后在内置名称表中查找

现在我完全理解了教程语句,但后来说这variables that are only referenced inside a function are implicitly global对我来说似乎很模糊.

如果我们真的开始查看本地符号表,然后按照更"通用"的表格,那么为什么说它们是隐式全局的呢?它只是一种说法,如果你只想在一个函数中引用一个变量,你不需要担心它是本地的还是global

Tho*_*zco 8

例子

(进一步了解摘要)

这意味着如果一个变量从未在函数体中赋值,那么它将被视为全局变量.

这解释了为什么以下工作(a被视为全局):

a = 1

def fn():
    print a  # This is "referencing a variable" == "reading its value"

# Prints: 1
Run Code Online (Sandbox Code Playgroud)

但是,如果将变量赋值给函数体中的某个位置,则它将被视为整个函数体的局部变量.

这包括分配之前找到的语句(请参阅下面的示例).

这就解释了为什么下面就无法正常工作.在这里,a被视为本地的,

a = 1

def fn():
    print a 
    a = 2  # <<< We're adding this

fn()

# Throws: UnboundLocalError: local variable 'a' referenced before assignment
Run Code Online (Sandbox Code Playgroud)

您可以让Python使用该语句将变量视为全局变量global a.如果这样做,则变量将被视为全局变量,同样适用于整个函数体.

a = 1

def fn():
   global a  # <<< We're adding this
   print a
   a = 2

fn()
print a

# Prints: 1
# Then, prints: 2 (a changed in the global scope too)
Run Code Online (Sandbox Code Playgroud)

摘要

与您可能期望的不同,如果在本地范围内找不到,Python将不会回退到全局a范围.

这意味着整个函数体的变量是局部变量或全局变量:它不能是全局的,然后变为局部变量.

现在,关于变量是被视为本地变量还是全局变量,Python遵循以下规则.变量是:

  • 全局如果仅引用且从未分配给
  • 全局如果使用该global语句
  • 本地如果变量至少被分配一次(并且global未被使用)

进一步说明

事实上,"隐含全球化"并不意味着全球化.这是一个更好的思考方式:

  • "local"意味着"函数内部的某个地方"
  • "全球"真的意味着"在功能之外的某个地方"

因此,如果变量是"隐式全局"(=="在函数外部"),那么它的"封闭范围"将首先被查找:

a = 25

def enclosing():
   a = 2
   def enclosed():
       print a
   enclosed()

enclosing()

# Prints 2, as supplied in the enclosing scope, instead of 25 (found in the global scope)
Run Code Online (Sandbox Code Playgroud)

现在,像往常一样,global让您引用全局范围.

a = 25

def enclosing():
   a = 2
   def enclosed():
       global a  # <<< We're adding this
       print a
   enclosed()

enclosing()

# Prints 25, as supplied in the global scope
Run Code Online (Sandbox Code Playgroud)

现在,如果你需要分配ain enclosed,并且想要aenclosing范围内改变值,而不是在全局范围内,那么你需要nonlocal,这是Python 3中的新功能.在Python 2中,你不能.