[英]Confusion about Python variable scope
我遇到了一些令我困惑的代码。 这是一个显示这个的最小例子:
# of course, the ... are not part of the actual code
some_var = {"key1":"value1" ... "keyN":"valueN"}
def some_func():
v = some_var["key1"]
代码有效,但我可以直接访问some_var
的事实让我困惑。 我最后一次编写一些Python代码时,我记得要像这样编写some_func
:
def some_func():
global some_var
v = some_var["key1"]
我在Windows 7 PC上使用Python 2.7.1。 2.7版本中有什么变化允许这个吗?
不,你不能在本地范围内重新分配some_var
。 考虑以下:
some_var = {}
def some_func():
# some_var[5] = 6
some_var = {1:2}
some_var[3] = 4
some_func()
print (repr(some_var)) # {}
您会看到some_func
的赋值实际上创建了一个局部变量,该变量会影响全局变量。 因此,取消注释该行将导致UnboundLocalError
- 您无法在定义之前访问变量。
如果要为该变量分配新值,则只需使用global
。
嵌套范围是在Python 2.1中引入的 ( 默认情况下在Python 2.2中启用 )(强调我的):
简而言之,当给定的变量名称未在函数内赋值(通过赋值或
def
,class
或import
语句)时,将在封闭范围的本地命名空间中查找对该变量的引用。 可以在PEP中找到对规则的更详细解释以及对实施的剖析。
在外部作用域中使用(例如调用或使用表达式)名称并指定它(在分配裸变量和指定变量指向的对象成员之间存在差异 - xy = ...
和x[...] = ...
算作方法调用!)。
如果要重新分配变量,则只需要声明变量来自外部作用域。 在Python 2,你只能做与全局变量(通过global var
),在Python 3,你可以使用abritarily嵌套作用域(如闭包)做nonlocal var
。
在示例中使用非局部变量不需要global
变量。 但是,只要您在该范围内的任何位置分配变量(带有上述赋值定义),就some_var = ...
- 所以在您使用它的行之后添加一行some_var = ...
并且您将获得UnboundLocalError
。 有关细节的详细信息,请参阅文档。
如果要分配给变量,则只需要使用global
,为了读取变量,这不是必需的 。 这种差异并不是随意的,尽管乍一看似乎是这样。
读取值时,解释器只能查找名为some_var
的局部变量,如果找不到它,则会查找该名称的全局变量。 这些是简单直接的语义。
将值赋给变量时,解释器需要知道您是否要分配给局部变量some_var
或全局变量。 解释器假设some_var = 2
在函数内调用时分配给局部变量,这是有意义的,因为这是最常见的情况 。 对于想要从函数中分配全局变量的相对罕见的时间,则使用全局修饰符global some_var = 2
。
它取决于函数Python变量范围错误中变量的用法
为名称赋值会使名称为local,除非名称显式声明为global。
a = 12
def foo():
a = 42
print a # uses local
foo()
>>> 42
def foo():
global a
a = 42
foo()
print a
>>> 42
如果未分配名称,则为全局名称。
a = 12
def foo():
print a # uses global
foo()
>>> 12
简而言之,如果要分配名称,则只需要明确声明全局名称。 如果您只是阅读它,您可以随意使用它。 但是,如果您分配给变量,除非您将其声明为全局,否则它将被视为该函数的本地变量。
b = 5
def foo():
print b
b = 7
foo()
>>> ???
由于b
在foo()
被赋值并且未被声明为全局,因此Python 在编译时决定b
是本地名称。 因此, b
是整个函数的本地名称, 包括在赋值之前的 print
语句中。
因此print
语句会给出错误,因为本地名称b
尚未定义!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.