我遇到了一些令我困惑的代码。这是一个显示这个的最小例子:
# 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版本中有什么变化允许这个吗?
答案 0 :(得分:6)
不,您无法在本地范围内重新分配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
- 您无法在定义之前访问变量。
答案 1 :(得分:3)
如果要为该变量分配新值,则只需使用global
。
Nested scope was introduced in Python 2.1(和enabled by default in Python 2.2)(强调我的):
简单地说,当给定的变量名称未在函数中指定值时(通过作业,或
def
,class
或{{1} }语句),对变量的引用将在在封闭范围的本地命名空间中查找。可以在PEP中找到有关规则的更详细说明以及对实施的剖析。
答案 2 :(得分:3)
使用(例如在表达式中调用或使用)来自外部作用域的名称和赋值它之间存在差异(并且在分配裸变量和指定变量指向的对象成员之间存在差异 - { {1}}和x.y = ...
计为方法调用!)。
如果要重新分配变量,则只需要声明变量来自外部作用域。在Python 2中,您只能使用全局变量(通过x[...] = ...
),在Python 3中,您可以使用global var
为abritarily嵌套作用域(例如闭包)执行此操作。
使用示例中的非本地变量不需要nonlocal var
。但是,只要您在该范围内的任何位置分配变量(具有上述分配定义),就可以在您使用它的行之后添加一行global
,然后您将获得{ {1}}。有关细节的详细信息,请参阅文档。
答案 3 :(得分:2)
如果您打算分配给变量,则只需要使用global
,因为读取变量不需要。这种差异并不是随意的,尽管乍一看似乎是这样。
当读取值时,解释器只能查找名为some_var
的局部变量,如果找不到它,则会查找该名称的全局变量。这些都是简单直接的语义。
为变量赋值时,解释器需要知道您是要分配给局部变量some_var
还是全局变量。 解释器假设在函数内调用时some_var = 2
分配给局部变量,这是有意义的,因为这是最常见的情况。对于您希望从函数中分配全局变量的相对罕见的时间,您可以使用全局修饰符global some_var = 2
。
答案 4 :(得分:1)
这取决于函数中变量的用法 Python variable scope error
答案 5 :(得分:1)
为名称赋值会使名称为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
语句。 < / p>
因此,print
语句会给您一个错误,因为尚未定义本地名称b
!