在python2/3中访问函数内部的全局变量时出现异常

2024-04-16 11:22:12 发布

您现在位置:Python中文网/ 问答频道 /正文

如果不使用Global关键字,就不能在函数中访问全局变量;(很好),但我没有想到会出现以下情况:

案例1:

a = 1

def f():
  a += 1
  print(a)

>>> f()
...
UnboundLocalError: local variable 'a' referenced before assignment

原因我推测:函数在其局部范围内找不到变量a。你知道吗

案例2:

a = 1

def f():
  print(a)

>>> f()
1

但是现在,函数在其局部范围内找到变量a。 与我在上一个案子中推测的原因相矛盾。你知道吗

为什么会这样?你知道吗


Tags: 函数localdef情况原因局部关键字variable
1条回答
网友
1楼 · 发布于 2024-04-16 11:22:12

这是因为对于第二个示例,编译器试图用一些魔法来帮助您。如果是

def f():
  print(a)

下面是它简化为的字节码:

dis.dis(f)
  2           0 LOAD_GLOBAL              0 (print) 
              3 LOAD_GLOBAL              1 (a) #aha!
              6 CALL_FUNCTION            1 (1 positional, 0 keyword pair) 
              9 POP_TOP              
             10 LOAD_CONST               0 (None) 
             13 RETURN_VALUE

您可以看到,由于您从未分配给a范围内的f,编译器知道您必须引用一个全局变量。你知道吗

当您开始赋值给a时,现在编译器不会试图帮助您。除非您明确告诉它a是全局的,否则它将把它当作局部的。你知道吗

def g():
    x += 1

dis.dis(g)
  2           0 LOAD_FAST                0 (x) #note no assumption that it is global
              3 LOAD_CONST               1 (1) 
              6 INPLACE_ADD          
              7 STORE_FAST               0 (x) 
             10 LOAD_CONST               0 (None) 
             13 RETURN_VALUE  

现在你可以问这个问题了,好吧,但是为什么编译器在你的第一个例子中没有帮助你呢?当然,解释它的一种方法是“显式优于隐式”。当然,在第二个示例中,编译器隐式地执行一些操作,所以这可能不是一个令人满意的解释:)。你知道吗

我认为,归根结底,这就是Python的工作方式。如果将变量赋值,python视为该范围的局部变量,除非另行说明。所以你的陈述是:

Global variables cannot be accessed within a function without using the global keyword

不太正确。您可以从外部作用域访问变量,但如果不明确声明您想要,则不能赋值给所述变量。你知道吗


旁注,这是完全合法的:

x = [1]

def f():
    x[0] += 1

f()
#x is now [2]

这可能会让人困惑:-)。这是因为在这个上下文中,您没有在x持有的引用上赋值;+=操作符实际上调用列表的__setattr__方法来更改属性。在python2中,这个技巧经常被用作解决没有nonlocal关键字的问题的方法。你知道吗

相关问题 更多 >