繁体   English   中英

关于Python变量范围的困惑

[英]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中启用 )(强调我的):

简而言之,当给定的变量名称在函数内赋值(通过赋值或defclassimport语句)时,将在封闭范围的本地命名空间中查找对该变量的引用。 可以在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()
>>> ???

由于bfoo()被赋值并且未被声明为全局,因此Python 在编译时决定b是本地名称。 因此, b整个函数的本地名称 包括赋值之前的 print语句中

因此print语句会给出错误,因为本地名称b尚未定义!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM