Копирует ли Python значение или ссылку на экземпляр объекта? - PullRequest
10 голосов
/ 04 июня 2010

Возможно, простой вопрос, но я не могу точно сформулировать свой запрос 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']

Ответы [ 2 ]

13 голосов
/ 04 июня 2010

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

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

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

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

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

1 голос
/ 04 июня 2010

кажется, что нет необходимости

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

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

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

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

...