2013-04-06 4 views
3

Кажется, что a = a-b отличается от a -= b, и я не знаю почему.Python «a = a-b» и «a- = b» действительно эквивалентны?

Код:

cache = {} 
def part(word): 
    if word in cache: 
     return cache[word] 
    else: 
     uniq = set(word) 
     cache[word] = uniq 
     return uniq 

w1 = "dummy" 
w2 = "funny" 

# works 
test = part(w1) 
print(test) 
test = test-part(w2) 
print(test) 
print(cache) 

# dont't works 
test = part(w1) 
print(test) 
test -= part(w2) # why it touches "cache"? 
print(test) 
print(cache) 

Результат:

set(['y', 'm', 'u', 'd']) 
set(['m', 'd']) 
{'dummy': set(['y', 'm', 'u', 'd']), 'funny': set(['y', 'n', 'u', 'f'])} 
set(['y', 'm', 'u', 'd']) 
set(['d', 'm']) 
{'dummy': set(['d', 'm']), 'funny': set(['y', 'n', 'u', 'f'])} 

Как вы можете видеть, третья и последняя строка отличается. Почему во втором случае переменная «кеш» отличается? test -= part(w2) не похож на test = test-part(w2)?

Редактировать 1 - Спасибо за ответы, но почему изменяется var cache?

ответ

6

Да, они разные. Сравните следующее:

>>> x = set([1,2,3]) 
>>> y = x 
>>> y -= set([1]) 
>>> x 
set([2, 3]) 

>>> map(id, (x, y)) 
[18641904, 18641904] 

с

>>> x = set([1,2,3]) 
>>> y = x 
>>> y = y - set([1]) 
>>> x 
set([1, 2, 3]) 

>>> map(id, (x, y)) 
[2774000, 21166000] 

Другими словами, y -= set(...) изменения y на месте. Поскольку оба x и y относятся к одному и тому же объекту, они оба изменяются.

С другой стороны, y = y - set(...) создает новый объект, переплетая y для обращения к этому новому объекту. x не изменяется, поскольку он все еще указывает на старый объект.

+0

Извините, но я не понимаю, почему «кеш» изменяется: в моем коде нет «кеша = тест» или подобных строк. –

+0

@FrancescoFrassinelli: вы возвращаете ссылки на объекты, хранящиеся в кеше. Если объект изменен с помощью такой ссылки, содержимое кеша изменяется. – NPE

6

a = a - b - это операция, которая заменяет a новым объектом - результатом a - b.

a -= b - это операция, которая работает на a на месте и изменяет ее с использованием b.

В некоторых случаях эти два эквивалента, на других - нет. Очевидный случай - об неизменяемых объектах, где они действуют одинаково. На изменяемых объектах, как вы обнаружили, есть большая разница.

+0

Извините, но я не понимаю, почему изменяется «кеш». –

+0

@FrancescoFrassinelli Поскольку в Python переменные являются именами, ссылающимися на объекты. Вы нанесли еще один тег имени ('cache') на свой объект, поэтому, когда вы меняете его, используя имя' a', он не будет волшебным образом не изменяться под другим именем. –