Ý nghĩa của x[...]dưới đây là gì?
a = np.arange(6).reshape(2,3)
for x in np.nditer(a, op_flags=['readwrite']):
x[...] = 2 * x
Ý nghĩa của x[...]dưới đây là gì?
a = np.arange(6).reshape(2,3)
for x in np.nditer(a, op_flags=['readwrite']):
x[...] = 2 * x
Câu trả lời:
Trong khi bản sao được đề xuất Đối tượng Dấu ba chấm trong Python làm gì? trả lời câu hỏi trong pythonbối cảnh chung , việc sử dụng nó trong một nditervòng lặp yêu cầu, tôi nghĩ, thêm thông tin.
https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#modizing-array-values
Phép gán thông thường trong Python chỉ đơn giản là thay đổi một tham chiếu trong từ điển biến cục bộ hoặc toàn cục thay vì sửa đổi một biến hiện có tại chỗ. Điều này có nghĩa là chỉ cần gán cho x sẽ không đặt giá trị vào phần tử của mảng, mà chuyển x từ tham chiếu phần tử mảng thành tham chiếu đến giá trị bạn đã gán. Để thực sự sửa đổi phần tử của mảng, x phải được lập chỉ mục bằng dấu chấm lửng.
Phần đó bao gồm ví dụ mã của bạn.
Vì vậy, theo cách nói của tôi, x[...] = ...sửa đổi xtại chỗ; x = ...sẽ phá vỡ liên kết đến nditerbiến và không thay đổi nó. Nó giống như x[:] = ...nhưng hoạt động với các mảng có kích thước bất kỳ (bao gồm cả 0d). Trong bối cảnh xnày không chỉ là một số, mà là một mảng.
Có lẽ điều gần nhất với sự nditerlặp lại này mà không có nditerlà:
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]])
Lưu ý rằng tôi phải lập chỉ mục và sửa đổi a[i]trực tiếp. Tôi không thể đã sử dụng x = 2*x,. Trong lần lặp xnày là một đại lượng vô hướng và do đó không thể thay đổi
In [669]: for i,x in np.ndenumerate(a):
...: x[...] = 2 * x
...
TypeError: 'numpy.int32' object does not support item assignment
Nhưng trong nditertrường hợp xnày là một mảng 0d và có thể thay đổi.
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'> ()
...
Và bởi vì nó là 0d, x[:]không thể được sử dụng thay thế chox[...]
----> 3 x[:] = 2 * x
IndexError: too many indices for array
Việc lặp lại mảng đơn giản hơn cũng có thể cung cấp thông tin chi tiết:
In [675]: for x in a:
...: print(x, x.shape)
...: x[:] = 2 * x
...:
[ 0 8 16] (3,)
[24 32 40] (3,)
điều này lặp lại trên các hàng (mờ đầu tiên) của a. xsau đó là mảng 1d và có thể được sửa đổi bằng x[:]=...hoặc x[...]=....
Và nếu tôi thêm các external_looplá cờ từ tiếp theo phần , xbây giờ là một mảng 1d, và x[:] =sẽ làm việc. Nhưng x[...] =vẫn hoạt động và tổng quát hơn. x[...]được sử dụng tất cả các nditerví dụ khác .
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,)
So sánh lần lặp hàng đơn giản này (trên mảng 2d):
In [675]: for x in a:
...: print(x, x.shape)
...: x[:] = 2 * x
...:
[ 0 8 16] (3,)
[24 32 40] (3,)
điều này lặp lại trên các hàng (mờ đầu tiên) của a. xsau đó là mảng 1d và có thể được sửa đổi bằng x[:] = ...hoặc x[...] = ....
Đọc và thử nghiệm với nditertrang này từ đầu đến cuối. Tự nó, nditerkhông phải là hữu ích trong python. Nó không tăng tốc độ lặp lại - không cho đến khi bạn chuyển mã của mình sang cython. np.ndindexlà một trong số ít các numpyhàm không được biên dịch sử dụng nditer.