Подтвердить что ты не робот

Копирует ли значение Python или ссылку на экземпляр объекта?

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

...
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'

Итак, что это за настоящая история? Спасибо!

EDIT:

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

>>> flav = ['a','b']
>>> a = Candy(flav)
>>> a.flavor
['a', 'b']
>>> flav[1] = 'c'
>>> flav
['a', 'c']
>>> a.flavor
['a', 'c']
4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

кажется, что это необязательно

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

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

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

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