Python копирует значение или ссылку после объектного инстанцирования?

Простой вопрос, возможно, но я не могу вполне формулировать свой запрос Google для нахождения ответа здесь. У меня была привычка к созданию копий объектов, когда я передаю их в конструкторов Object, как так:

...
def __init__(self, name):
    self._name = name[:]
...

Однако, когда я выполнил следующий тестовый код, это, кажется, не необходимо, что Python делает глубокие копии объектных значений после объектного инстанцирования:

>>> class Candy(object):
...     def __init__(self, flavor):
...             self.flavor = flavor
...
>>> flav = "cherry"
>>> a = Candy(flav)
>>> a
<__main__.Candy object at 0x00CA4670>
>>> a.flavor
'cherry'
>>> flav += ' and grape'
>>> flav
'cherry and grape'
>>> a.flavor
'cherry'

Так, какова реальная история здесь?Спасибо!

Править:

Благодаря @Olivier для его большого ответа. Следующий код документирует лучший пример, который Python действительно копирует ссылкой:

>>> flav = ['a','b']
>>> a = Candy(flav)
>>> a.flavor
['a', 'b']
>>> flav[1] = 'c'
>>> flav
['a', 'c']
>>> a.flavor
['a', 'c']
10
задан daveslab 4 June 2010 в 14:09
поделиться

2 ответа

Это потому, что строки неизменяемы.

Оператор +=, как это ни странно, фактически переназначает переменную, к которой он применяется, если объект неизменяем:

s = 'a'
ids = id(s)
s += 'b'
ids == id(s) # False, because s was reassigned to a new object

Итак, в вашем случае, в начале, и flav, и a. flavor указывают на один и тот же строковый объект:

flav --------\
               'cherry'
a.flavor ----/

Но когда вы пишете flav += 'and grape', переменная flav получает переназначение на новый строковый объект:

flav --------> 'cherry and grape'
a.flavor ----> 'cherry' # <-- that string object never changes

Это сбивает с толку, потому что обычно, когда вы вызываете оператор на переменной, он не изменяет переменную. Но как раз в случае с неизменяемым объектом он переназначает переменную.

Итак, окончательный ответ на ваш вопрос: да, имеет смысл копировать объекты при инстанцировании, особенно если вы ожидаете получить изменяемый объект (что часто бывает). Если объект неизменяемый, то копирование в любом случае не повредит.

13
ответ дан 3 December 2019 в 23:11
поделиться

кажется, не нужно

Появляется? Ваш вопрос полностью о дизайне и значении. Это не вопрос предпочтений или привычки.

Включает ли контракт класса возможность изменять изменяемый аргумент? В таком случае НЕ делайте копию.

Утверждает ли контракт класса, что изменяемый аргумент не будет изменен? Если да, вы ДОЛЖНЫ сделать копию.

На ваши вопросы отвечает полностью определение контракта для класса.

1
ответ дан 3 December 2019 в 23:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: