Điều này phụ thuộc hoàn toàn vào đối tượng i
.
+=
gọi __iadd__
phương thức (nếu nó tồn tại - quay trở lại __add__
nếu nó không tồn tại) trong khi +
gọi __add__
phương thức 1 hoặc __radd__
phương thức trong một vài trường hợp 2 .
Từ phối cảnh API, __iadd__
được cho là được sử dụng để sửa đổi các đối tượng có thể thay đổi tại chỗ (trả lại đối tượng đã bị thay đổi) trong khi __add__
sẽ trả về một thể hiện mới của một cái gì đó. Đối với các đối tượng không thay đổi , cả hai phương thức đều trả về một thể hiện mới, nhưng __iadd__
sẽ đặt thể hiện mới vào không gian tên hiện tại với cùng tên mà thể hiện cũ có. Đây là lý do tại sao
i = 1
i += 1
dường như tăng lên i
. Trong thực tế, bạn nhận được một số nguyên mới và gán nó "trên đầu trang" i
- mất một tham chiếu đến số nguyên cũ. Trong trường hợp này, i += 1
hoàn toàn giống như i = i + 1
. Nhưng, với hầu hết các đối tượng có thể thay đổi, đó là một câu chuyện khác:
Như một ví dụ cụ thể:
a = [1, 2, 3]
b = a
b += [1, 2, 3]
print a #[1, 2, 3, 1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]
so với:
a = [1, 2, 3]
b = a
b = b + [1, 2, 3]
print a #[1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]
thông báo như thế nào trong ví dụ đầu tiên, kể từ b
và a
tham khảo cùng một đối tượng, khi tôi sử dụng +=
trên b
, nó thực sự thay đổi b
(và a
nhìn thấy sự thay đổi đó quá - Sau khi tất cả, nó tham khảo danh sách giống nhau). Tuy nhiên, trong trường hợp thứ hai, khi tôi thực hiện b = b + [1, 2, 3]
, điều này sẽ đưa danh sách b
tham chiếu và nối nó với một danh sách mới [1, 2, 3]
. Sau đó, nó lưu trữ danh sách được nối trong không gian tên hiện tại dưới dạng b
- Không liên quan b
đến dòng trước đó là gì .
1 Trong biểu thức x + y
, nếu x.__add__
không thực hiện hoặc nếu x.__add__(y)
lợi nhuận NotImplemented
và x
và y
có các loại khác nhau , sau đó x + y
cố gắng để gọi y.__radd__(x)
. Vì vậy, trong trường hợp bạn có
foo_instance += bar_instance
nếu Foo
không thực hiện __add__
hoặc __iadd__
sau đó kết quả ở đây giống như
foo_instance = bar_instance.__radd__(bar_instance, foo_instance)
2 Trong biểu thức foo_instance + bar_instance
, bar_instance.__radd__
sẽ được thử trước foo_instance.__add__
nếu loại bar_instance
là một lớp con của loại foo_instance
(ví dụ issubclass(Bar, Foo)
). Các hợp lý cho điều này là bởi vì Bar
là trong một ý nghĩa một "cấp cao" đối tượng hơn Foo
nên Bar
sẽ nhận được tùy chọn của trọng Foo
hành vi 's.
+=
hành động nhưextend()
trong trường hợp danh sách.