首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python :为什么说只引用的变量是隐式全局的?

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

Stack Overflow用户
提问于 2014-05-04 16:48:18
回答 4查看 501关注 0票数 6

Python常见问题中,我们可以读到:

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

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

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

现在,我完全理解了教程中的语句,但接着说,variables that are only referenced inside a function are implicitly global对我来说似乎相当模糊。

如果我们实际上开始查看本地符号表,然后使用更“通用”的表,那么为什么说它们是隐含的全局的呢?这仅仅是一种说法吗?如果您只想在函数中引用一个变量,那么您不需要担心它是本地变量还是global变量

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-05-04 16:54:33

示例

(有关摘要,请参阅下文)

这意味着,如果--如果变量是--在函数体中从未分配给,那么它将被视为全局变量。

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

代码语言:javascript
复制
a = 1

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

# Prints: 1

但是,如果变量被分配到函数的body中的某个位置,那么它将被视为整个函数体的本地

这包括在分配给它之前找到的语句(参见下面的示例)。

这就解释了为什么下面的不工作。在这里,a被视为本地的,

代码语言:javascript
复制
a = 1

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

fn()

# Throws: UnboundLocalError: local variable 'a' referenced before assignment

您可以让Python使用global a语句将变量视为全局变量。如果这样做,那么变量将再次被视为全局的,,对于整个函数体。

代码语言:javascript
复制
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)

摘要

与您可能预期的不同,如果无法在本地作用域中找到,Python将不会返回到全局范围。

这意味着变量是整个函数体的本地或全局:它不能是全局的,然后变成本地的。

现在,关于变量是本地的还是全局的,Python遵循以下规则。变量是:

  • 全局的,如果只引用并且从未分配给
  • 如果使用global语句,则为全局
  • 如果变量至少分配给一次,则为局部变量(并且没有使用global )

进一步说明

事实上,“隐式全球化”并不意味着全球性。下面是一个更好的思考方法:

  • “本地”的意思是“函数的某个地方”
  • “全局”的真正意思是“函数之外的某个地方”

因此,如果一个变量是“隐式全局的”(==“在函数之外”),那么将首先查找它的“封闭作用域”:

代码语言:javascript
复制
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)

现在,和往常一样,global允许您引用全局范围。

代码语言:javascript
复制
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

现在,如果您需要在a中指定enclosed,并且希望在enclosing的作用域中而不是在全局范围内更改a的值,那么您将需要nonlocal,这在Python3中是新的。在Python2中,您不能。

票数 8
EN

Stack Overflow用户

发布于 2014-05-04 16:54:44

Python的名称解析方案有时被称为LEGB规则,以范围名称之后的名称命名.

当在函数中使用非限定名时,Python最多搜索四个作用域--本地(L)作用域,然后搜索包含(E) defs和lambdas的本地作用域,然后搜索全局(G)作用域,然后搜索内置(B)作用域,并在找到名称的第一处停止。如果在此搜索过程中找不到名称,Python将报告一个错误。

  • 默认情况下,名称分配会创建或更改本地名称。
  • 名称引用搜索最多有四个作用域:本地,然后封装函数(如果有的话),然后是全局的,然后是内置的。
  • 全局语句和非本地语句中声明的名称分别将指定的名称映射到封装模块和函数作用域。

换句话说,默认情况下,函数def语句(或lambda)中分配的所有名称都是局部变量。函数可以自由地使用在语法上包围函数和全局范围中分配的名称,但是它们必须声明这样的nonlocalsglobals才能更改它们。

参考资料:http://goo.gl/woLW0F

票数 1
EN

Stack Overflow用户

发布于 2014-05-04 16:55:07

这是令人困惑的,而且文档可能会更加清晰。

此上下文中的“所引用”意味着名称不是分配给的,而是简单地从。例如,当a = 1分配给a时,print(a) (Python3语法)引用的是没有任何赋值的a

如果您像上面一样引用a而没有任何赋值,那么Python解释器会递归地搜索当前名称空间的父名称空间,直到它到达全局命名空间为止。

另一方面,如果将变量赋值给一个变量,则该变量仅在本地命名空间中定义,除非使用global关键字另作声明。因此,a = 1在本地命名空间中创建了一个新名称a。在更高的命名空间中,这优先于任何其他名为a的变量。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23458854

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档