2010-01-08 2 views
4
>>> c = [1, 2, 3] 
>>> print(c, id(c)) 
[1, 2, 3] 43955984 
>>> c += c 
>>> print(c, id(c)) 
[1, 2, 3, 1, 2, 3] 43955984 
>>> del c 
>>> c = [1, 2, 3] 
>>> print(c, id(c)) 
[1, 2, 3] 44023976 
>>> c = c + c 
>>> print(c, id(c)) 
[1, 2, 3, 1, 2, 3] 26564048 

В чем разница? + = и + не должны быть просто синтаксическим сахаром?+ и + = разные операторы?

+1

Ваш пример ясно показывает, что это не так. + = явно добавляется к этому объекту, а x = a + b (даже если a = b = x) явно создаст новый результат и назначит его LHS. Я думаю, что было бы контрпродуктивно проверять каждое дополнение, чтобы увидеть, было ли это простое добавление (как указано выше) и оптимизировать его до + =. – Lazarus

+0

почему нисходящий?Я признаю, что название может быть лучше, но сам вопрос вполне применим. – Kimvais

+0

У этого вопроса есть какая-то приятная дополнительная информация о операциях конкатенации списков http://stackoverflow.com/questions/2022031/python-append-vs-operator-on-lists -why-do-these-give-different-results – Kimvais

ответ

13

docs explain it very well, я думаю, :

__iadd__() и т.д.
Эти методы вызываются для выполнения арифметических дополненных заданий (+=, -=, *=, /=, //=, %=, **=, <<=, >>=, &=, ^=, |=). Эти методы должны попытаться выполнить операцию на месте (изменение self) и вернуть результат (который может быть, но не обязательно, self). Если конкретный метод не определен, расширенное присваивание возвращается к обычным методам. Например, для выполнения оператора x += y, где x является экземпляром класса, который имеет метод __iadd__(), вызывается x.__iadd__(y).

+= предназначены для реализации модификации на месте. в случае простого добавления создается новый объект, и он помечен с использованием уже использованного имени (c).

Кроме того, вы заметили, что такое поведение оператора += возможно только из-за изменчивого характера списков. Целый - неизменный типа - не будет производить один и тот же результат:

>>> c = 3 
>>> print(c, id(c)) 
3 505389080 
>>> c += c 
>>> print(c, id(c)) 
6 505389128 
+0

Другим моментом является порядок оценки/приоритета. в 'c = c + c'' c + c' оценивается перед присваиванием 'c =', где, как и в 'c + = c', нет двух разных операций как таковых. – Kimvais

+0

вот что я говорю :) – SilentGhost

3

Они не такие же

с + = с присоединять копию содержания С в С собой

с = C + C создать новый объект с с + с

1

Оператор + = добавляет второй список к первому, но модификация на месте, так что идентификатор остается тем же самым.

Когда вы используете +, создается новый список, а окончательный «c» - это новый список, поэтому он имеет другой идентификатор.

Конечный результат для обеих операций одинаковый.

2

Для

foo = [] 

foo+=foo является синтаксически foo.extend(foo) (а не foo = foo + foo)

В первом случае, вы просто добавление членов списка в другой (а не создание нового).

id Изменения во втором случае, поскольку новый список создается путем добавления двух списков. Случайно, что оба они одинаковы, и результат привязан к одному и тому же идентификатору, чем один раз указывал на них.

Если вы перефразируете этот вопрос разными списками (а не самим c), это, вероятно, станет яснее.

Смежные вопросы