我试图遍历一个numpy数组并更改其中的一些值。这是我的代码,实际上是从文档(numpy nditer docs)复制而来的:
import numpy as np
a = np.arange(6).reshape(2,3)
print(a)
with np.nditer(a, op_flags=['readwrite']) as it:
for x in it:
x[...] = 2 * x
print(a)
但我一直得到以下追溯:
Traceback (most recent call last):
File "text.py", line 5, in <module>
with np.nditer(a, op_flags=['readwrite']) as it:
AttributeError: __enter__
我是在做错什么,还是文档中有错误(是否已弃用
nditer
中的with
?)? 最佳答案
您正在查看Numpy 1.15的文档,该文档使用new feature of nditer()
introduced in that release:
在某些情况下,必须在上下文管理器中使用nditer
当将numpy.nditer
与"writeonly"
或"readwrite"
标志一起使用时,在某些情况下nditer
并不能真正为您提供可写数组的视图。相反,它会为您提供一个副本,并且如果您对该副本进行更改,nditer
稍后会将这些更改写回到您的实际数组中。当前,这种写回操作是在对数组对象进行垃圾回收时发生的,这使得该API在CPython上容易出错,而在PyPy上则完全损坏。因此,每当nditer
与可写数组(例如with np.nditer(...) as it: ...
)一起使用时,都应将其用作上下文管理器。对于上下文管理器不可用的情况,例如在生成器表达式中,您也可以显式调用it.close()
。
该错误表明您使用的是Numpy的早期版本; with
语句仅适用于*上下文管理器(must implement __exit__
(and __enter__
)),而AttributeError
异常表示在您的Numpy版本中,所需的实现不存在。
要么升级,要么不使用with
:
for x in np.nditer(a, op_flags=['readwrite']):
x[...] = 2 * x
但是,在使用CPython时,您仍可能会遇到导致1.15版本中所做更改的问题。使用PyPy时,您会遇到这些问题,而升级是您唯一的适当选择。
您可能要引用1.14 version of the same documentation entry you used(或更具体地,请确保pick the right documentation for your local version。