2017-02-12 36 views

回答

15

雖然擬議的重複What does the Python Ellipsis object do?答案在一般情況下python的問題,其在nditer循環使用需要,我想補充信息。在Python

https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#modifying-array-values

常規分配只是改變了局部或全局變量參考字典而不是就地修改現有的變量。這意味着簡單地賦值給x將不會將值放入數組的元素中,而是將x從數組元素引用切換爲對您分配的值的引用。要實際修改數組的元素,x應該用省略號索引。

該部分包含您的代碼示例。

所以用我的話說,x[...] = ...修改x就地; x = ...將打破鏈接到nditer變量,並沒有改變它。這就像x[:] = ...,但可以與任何維度的數組(包括0d)一起使用。在這方面x不只是一個數字,它是一個數組。

也許是最接近這個nditer迭代,沒有nditer是:

In [667]: for i, x in np.ndenumerate(a): 
    ...:  print(i, x) 
    ...:  a[i] = 2 * x 
    ...:  
(0, 0) 0 
(0, 1) 1 
... 
(1, 2) 5 
In [668]: a 
Out[668]: 
array([[ 0, 2, 4], 
     [ 6, 8, 10]]) 

請注意,我不得不指數和直接修改a[i]。我不能使用,x = 2*x。在此迭代x是一個標量,並因此不可變

In [669]: for i,x in np.ndenumerate(a): 
    ...:  x[...] = 2 * x 
    ... 
TypeError: 'numpy.int32' object does not support item assignment 

但在nditer的情況下x是0D陣列,和可變的。

In [671]: for x in np.nditer(a, op_flags=['readwrite']): 
    ...:  print(x, type(x), x.shape) 
    ...:  x[...] = 2 * x 
    ...:  
0 <class 'numpy.ndarray'>() 
4 <class 'numpy.ndarray'>() 
... 

而且因爲它是0D,x[:]不能用來代替x[...]

----> 3  x[:] = 2 * x 
IndexError: too many indices for array 

一個簡單數組迭代也可能洞察:

In [675]: for x in a: 
    ...:  print(x, x.shape) 
    ...:  x[:] = 2 * x 
    ...:  
[ 0 8 16] (3,) 
[24 32 40] (3,) 

就行這個迭代(第1暗淡)的a。然後x是1d陣列,可以用x[:]=...x[...]=...修改。

如果我從下section添加external_loop標誌,x現在是一維數組,並x[:] =會工作。但x[...] =仍然有效,更一般。 x[...]用於所有其他nditer示例。

In [677]: for x in np.nditer(a, op_flags=['readwrite'], flags=['external_loop']): 
    ...:  print(x, type(x), x.shape) 
    ...:  x[...] = 2 * x 
[ 0 16 32 48 64 80] <class 'numpy.ndarray'> (6,) 

比較這個簡單的行迭代(2D陣列上):的a

In [675]: for x in a: 
    ...:  print(x, x.shape) 
    ...:  x[:] = 2 * x 
    ...:  
[ 0 8 16] (3,) 
[24 32 40] (3,) 

上的行這個迭代(第一暗淡)。 x然後是1d陣列,並且可以用x[:] = ...x[...] = ...修改。

閱讀並試驗這個nditer頁面一直到最後。本身,nditerpython中沒有用處。它不會加速迭代 - 直到將代碼移植到cythonnp.ndindex是少數使用nditer的非編譯numpy函數之一。