2016-03-17 54 views
6

Tôi cần một lời giải thích tốt (tham khảo) để giải thích NumPy cắt trong vòng (for) vòng lặp. Tôi có ba trường hợp.Cắt một mảng NumPy trong một vòng

def example1(array): 
    for row in array: 
     row = row + 1 
    return array 

def example2(array): 
    for row in array: 
     row += 1 
    return array 

def example3(array): 
    for row in array: 
     row[:] = row + 1 
    return array 

Một trường hợp đơn giản:

ex1 = np.arange(9).reshape(3, 3) 
ex2 = ex1.copy() 
ex3 = ex1.copy() 

lợi nhuận:

>>> example1(ex1) 
array([[0, 1, 2], 
     [3, 4, 5], 
     [6, 7, 8]]) 

>>> example2(ex2) 
array([[1, 2, 3], 
     [4, 5, 6], 
     [7, 8, 9]]) 

>>> example3(ex3) 
array([[1, 2, 3], 
     [4, 5, 6], 
     [7, 8, 9]]) 

Có thể thấy rằng kết quả đầu tiên khác với thứ hai và thứ ba.

+2

Câu hỏi liên quan, hy vọng điều này sẽ giúp http://stackoverflow.com/questions/15376509/when-is-i-x-different-from-i-i-x-in-python/15376520#15376520 – Thiru

Trả lời

4

Ví dụ đầu tiên:

Bạn trích xuất một hàng và thêm 1 vào đó. Sau đó, bạn xác định lại các con trỏ row nhưng không phải những gì array chứa! Vì vậy, nó sẽ không ảnh hưởng đến mảng ban đầu.

Thứ hai ví dụ:

Bạn thực hiện một hoạt động tại chỗ - rõ ràng điều này sẽ ảnh hưởng đến các mảng ban đầu - miễn là nó là một mảng.

Nếu bạn đang làm một vòng lặp đôi nó sẽ không có tác dụng nữa:

def example4(array): 
    for row in array: 
     for column in row: 
      column += 1 
    return array 

example4(np.arange(9).reshape(3,3)) 
array([[0, 1, 2], 
     [3, 4, 5], 
     [6, 7, 8]]) 

này không làm việc vì bạn không gọi np.ndarray 's __iadd__ (để sửa đổi dữ liệu các điểm mảng) nhưng python int 's __iadd__. Vì vậy, ví dụ này chỉ hoạt động vì các hàng của bạn là mảng có nhiều mảng.

Thứ ba ví dụ:

row[:] = row + 1 này được hiểu như là một cái gì đó giống như row[0] = row[0]+1, row[1] = row[1]+1, ... một lần nữa làm việc này thay vì vậy đây ảnh hưởng đến mảng gốc.

Bottom Line

Nếu bạn đang hoạt động trên các đối tượng có thể thay đổi, giống như list s hoặc np.ndarray bạn cần phải cẩn thận những gì bạn thay đổi. Đối tượng như vậy chỉ có điểm đến nơi dữ liệu thực được lưu trữ trong bộ nhớ - vì vậy, việc thay đổi con trỏ (example1) này không ảnh hưởng đến dữ liệu đã lưu. Bạn cần phải đi theo con trỏ (hoặc trực tiếp bằng [:] (example3) hoặc gián tiếp với array.__iadd__ (example2)) để thay đổi dữ liệu đã lưu.

3

Trong mã đầu tiên, bạn không làm bất kỳ điều gì với hàng được tính toán mới; bạn rebind tên row, và không có kết nối với mảng nữa.

Trong phần thứ hai và thứ ba, bạn không rebind, nhưng gán giá trị cho biến cũ. Với += một số chức năng nội bộ được gọi, thay đổi tùy thuộc vào loại đối tượng bạn cho phép nó hoạt động. Xem các liên kết bên dưới.

Nếu bạn viết row + 1 ở phía bên tay phải, một mảng mới sẽ được tính toán. Trong trường hợp đầu tiên, bạn yêu cầu python đặt tên là row (và quên đối tượng ban đầu được gọi là row trước đó).Và trong phần ba, mảng mới được ghi vào lát của số row cũ.

Để đọc thêm, hãy làm theo liên kết nhận xét cho câu hỏi của @Thiru ở trên. Hoặc đọc về assignment and rebinding in general...

Các vấn đề liên quan