2

I am trying to iterate over a numpy array and change some values inside it. Here's my code, it's literally copied from the documentation (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)

But I keep getting the following traceback:

Traceback (most recent call last):
  File "text.py", line 5, in <module>
    with np.nditer(a, op_flags=['readwrite']) as it:
AttributeError: __enter__

Am I doing something incorrectly, or is there a mistake in the docs (is the usage of nditer inside with deprecated)?

s1512783
  • 23
  • 1
  • 5
  • 2
    That probably means your numpy version is too old. `__enter__` is called by `with`, but that's not implemented in your version. – Martijn Pieters Sep 02 '18 at 17:42
  • Check comments in this other recent nditer question, https://stackoverflow.com/q/52135891/901925 – hpaulj Sep 02 '18 at 17:53

1 Answers1

3

You are looking at the documentation for Numpy 1.15, and this uses a new feature of nditer() introduced in that release:

Under certain conditions, nditer must be used in a context manager

When using an numpy.nditer with the "writeonly" or "readwrite" flags, there are some circumstances where nditer doesn’t actually give you a view of the writable array. Instead, it gives you a copy, and if you make changes to the copy, nditer later writes those changes back into your actual array. Currently, this writeback occurs when the array objects are garbage collected, which makes this API error-prone on CPython and entirely broken on PyPy. Therefore, nditer should now be used as a context manager whenever it is used with writeable arrays, e.g., with np.nditer(...) as it: .... You may also explicitly call it.close() for cases where a context manager is unusable, for instance in generator expressions.

The error indicates you have an earlier version of Numpy; the with statement only works with context managers, which must implement __exit__ (and __enter__), and the AttributeError exception indicates that in your Numpy version the required implementation isn’t there.

Either upgrade, or don't use with:

for x in np.nditer(a, op_flags=['readwrite']):
    x[...] = 2 * x

When using CPython you may still run into the issues that caused the change made in the 1.15 release however. When using PyPy you will run into those issues, and upgrading is your only proper recourse.

You probably want to refer to the 1.14 version of the same documentation entry you used (or more specifically, make sure to pick the right documentation for your local version.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343