奇怪的Python / numpy UnboundLocalError行为

时间:2017-10-14 16:11:47

标签: python numpy

我正在使用Python 2.7.12和numpy 1.12.0并观察以下行为。这是预期的吗?我认为" a "属于范围w.r.t" f2 "在这两种情况下如何访问" a "与访问 a [ind,:] 不同?

import numpy as np
def f1():
   a = np.zeros((1, 10))
   def f2():
      print locals()
      v = [0] * 10
      v[3] = 1
      a += v
   f2()


def f11():
   a = np.zeros((1, 10))
   def f2():
      print locals()
      v = [0] * 10
      v[3] = 1
      a[0,:] = v
   f2()

结果:

>>> f11()
{'a': array([[ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]])}
>>> f1()
{}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in f1
  File "<stdin>", line 7, in f2
UnboundLocalError: local variable 'a' referenced before assignment
>>>

1 个答案:

答案 0 :(得分:1)

在您的第一个示例中,您使用了扩充分配

a += v

这使a成为本地变量;所有绑定操作(包括赋值)都会使变量成为局部变量。这是在编译时确定的。请参阅Python执行模型的Naming and binding section

  

如果名称绑定在块中,则它是该块的局部变量。

     

[...]

     

以下构造绑定名称: [...] 目标,如果在分配 [...] 中发生,则为标识符。

a是一个标识符的目标。

因为a被认为是本地的,在绑定之前尝试读取引用,将引发UnboundLocal异常。扩充分配必须先读取a才能分配回a,因此会出现异常。

您的第二个示例未绑定到a中任何位置的f2;分配给a切片不会改变名称a本身。您已分配到a[0,:];这不是一个标识符,而是一个切片。

您可以将a += v替换为np.add(a, v, out=a)来使第一个示例正常工作。