Простой вопрос, возможно, но я не могу вполне формулировать свой запрос 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']
Это потому, что строки неизменяемы.
Оператор +=
, как это ни странно, фактически переназначает переменную, к которой он применяется, если объект неизменяем:
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
Это сбивает с толку, потому что обычно, когда вы вызываете оператор на переменной, он не изменяет переменную. Но как раз в случае с неизменяемым объектом он переназначает переменную.
Итак, окончательный ответ на ваш вопрос: да, имеет смысл копировать объекты при инстанцировании, особенно если вы ожидаете получить изменяемый объект (что часто бывает). Если объект неизменяемый, то копирование в любом случае не повредит.
кажется, не нужно
Появляется? Ваш вопрос полностью о дизайне и значении. Это не вопрос предпочтений или привычки.
Включает ли контракт класса возможность изменять изменяемый аргумент? В таком случае НЕ делайте копию.
Утверждает ли контракт класса, что изменяемый аргумент не будет изменен? Если да, вы ДОЛЖНЫ сделать копию.
На ваши вопросы отвечает полностью определение контракта для класса.