2010-12-07 28 views
14

tôi chạy vào một cái gì đó thú vị về việc chuyển nhượng python tăng cường +=Python tăng cường phân công vấn đề

nó có vẻ là kiểu dữ liệu tự động chuyển đổi không phải luôn luôn làm cho a += b nếu a là một 'đơn giản' kiểu dữ liệu, trong khi a = a + b dường như làm việc luôn

trường hợp chuyển đổi được thực hiện

a = 1 
b = 1j 

a = 1 
b = 0.5 

trường hợp chuyển đổi không được thực hiện

from numpy import array 
a = array([0, 0 ,0]) 
b = array([0, 0, 1j]) 

sau a += b, a vẫn là ma trận số nguyên, thay vì ma trận phức tạp

tôi đã từng nghĩ a += b cũng giống như a = a + b, sự khác biệt của họ trong việc thực hiện cơ bản là gì? câu trả lời

+0

'mảng' trong ví dụ của bạn là gì? Đó có phải là từ mô-đun 'mảng' được xây dựng không? nếu như vậy, ví dụ của bạn thậm chí không hoạt động, vì không có typecode ... – SingleNegationElimination

+0

'a = array ([0, 0, 0])' và 'b = mảng ([0, 0, 1j])' don ' t làm việc với lớp 'mảng' trong mô-đun cùng tên. Cả hai đều thiếu một đối số * typecode * ban đầu. Và, AFAIK, lớp không hỗ trợ các số phức và cũng không được gán thêm '+ ='. Vì vậy, tôi không hiểu những gì bạn đang yêu cầu ở đây. – martineau

+0

@martineau Xem nhận xét của tôi về câu trả lời của Rafe (hiện đã bị xóa). Tham khảo câu hỏi NumPy này: http://www.scipy.org/FAQ#head-1ed851e9aff803d41d3cded8657b2b15a888ebd5 – ACoolie

Trả lời

15

Đối với các nhà điều hành +, Python xác định ba phương pháp "đặc biệt" mà một đối tượng có thể thực hiện:

  • __add__: thêm hai mục (+ điều hành). Khi bạn làm a + b, phương pháp __add__ của a được gọi với b như một cuộc tranh cãi.
  • __radd__: phản ánh thêm; cho a + b, phương pháp __radd__ của b được gọi với a như một ví dụ. Điều này chỉ được sử dụng khi a không biết cách thực hiện thêm và hai đối tượng là các loại khác nhau.
  • __iadd__: thêm tại chỗ; được sử dụng cho a += b trong đó kết quả được gán trở lại biến bên trái. Điều này được cung cấp riêng vì có thể thực hiện nó theo cách hiệu quả hơn. Ví dụ: nếu a là một danh sách, thì a += b giống với a.extend(b). Tuy nhiên, trong trường hợp của c = a + b bạn phải tạo một bản sao của a trước khi bạn mở rộng nó vì a không được sửa đổi trong trường hợp này. Lưu ý rằng nếu bạn không triển khai __iadd__ thì Python sẽ chỉ gọi số __add__ thay thế.

Vì vậy, kể từ khi các hoạt động khác nhau được thực hiện với phương pháp riêng biệt, có thể (nhưng thực tế thường xấu) để thực hiện chúng để họ làm những việc hoàn toàn khác nhau, hoặc có lẽ trong trường hợp này, chỉ hơi thứ khác nhau.

Những người khác đã suy luận rằng bạn đang sử dụng NumPy và giải thích hành vi của nó. Tuy nhiên, bạn đã hỏi về triển khai cơ bản. Hy vọng rằng bây giờ bạn thấy lý do tại sao đôi khi trường hợp a += b không giống như a = a + b. Bằng cách này, một bộ ba phương pháp tương tự cũng có thể được thực hiện cho các hoạt động khác. Xem this page để biết danh sách tất cả các phương pháp được hỗ trợ tại chỗ.

+1

Tôi nên lưu ý rằng trong ví dụ tôi đã đưa ra cho các danh sách, 'a + = b' thực tế có các kết quả khác nhau từ' a = a + b'. Nếu 'a' được biết bằng tên khác, tên kia sẽ" nhìn thấy "danh sách mở rộng sau' a + = b' nhưng không phải sau 'a = a + b'. – kindall

0

Rafe Kettler là đúng, nhưng có vẻ như bạn đã quản lý để có được a = [0,0,0] sau khi thêm nó vào b (theo bài viết của bạn).

Vâng, nếu bạn đang sử dụng NumPy hoặc scipy (Tôi nói điều này bởi vì tôi thấy array và tự hỏi điều gì mảng đang được tạo ra ở đây), thì đây là "bình thường", và thậm chí cần nâng cao một cảnh báo:

ComplexWarning: đúc giá trị phức tạp để vứt bỏ thực phần ảo

1

sự khác biệt giữa a = a + ba += b được, rằng việc bổ sung sau này sẽ, bất cứ khi nào có thể, thực hiện “tại chỗ” có nghĩa là bằng cách thay đổi các đối tượng a. Bạn có thể dễ dàng thấy điều này với danh sách.

a = b = [1, 2] 
a += [3] 
print b # [1, 2, 3] 
a = b = [1, 2] 
a = a + [3] 
print b # [1, 2] 
+0

Có, và trong trường hợp mảng numpy, điều đó có nghĩa là giữ kiểu 'a' giống nhau, vì vậy các số phức sẽ không được biểu diễn. – tkerwin

7

Nếu arraynumpy.array (bạn không thực sự rõ), sau đó các vấn đề đó đang xảy ra là bởi vì những mảng không thể thay đổi kiểu của chúng. Khi bạn tạo mảng mà không có một trình chỉ định kiểu, nó đoán một kiểu. Nếu sau đó bạn cố gắng thực hiện một thao tác mà loại không hỗ trợ (như thêm nó vào một loại có tên miền lớn hơn, như phức tạp), thì sẽ biết thực hiện phép tính, nhưng nó cũng biết rằng kết quả chỉ có thể được lưu trữ trong kiểu với tên miền lớn hơn. Nó phàn nàn (trên máy tính của tôi, dù sao, lần đầu tiên tôi làm một bài tập như vậy) rằng kết quả không phù hợp. Khi bạn thực hiện một bổ sung thường xuyên, một mảng mới phải được thực hiện trong mọi trường hợp, và gọn gàng cung cấp cho nó loại chính xác.

>>> a=numpy.array([1]) 
>>> a.dtype 
dtype('int32') 
>>> b=numpy.array([1+1j]) 
>>> b.dtype 
dtype('complex128') 
>>> a+b 
array([ 2.+1.j]) 
>>> (a+b).dtype 
dtype('complex128') 
>>> a+=b 
>>> a 
array([2]) 
>>> a.dtype 
dtype('int32') 
>>> 
Các vấn đề liên quan