Поскольку люди в комментариях здесь и в двух других вопросах, отмеченных как дубликаты, все, похоже, не понимают этого, я думаю, что стоит добавить дополнительный ответ поверх ответа Алекса Ковентри .
Тот факт, что Алекс присваивает значение изменяемого типа, например списка, не имеет ничего общего с тем, являются ли вещи общими или нет. Мы можем увидеть это с помощью id
функции или is
оператора:
>>> class A: foo = object()
>>> a, b = A(), A()
>>> a.foo is b.foo
True
>>> class A:
... def __init__(self): self.foo = object()
>>> a, b = A(), A()
>>> a.foo is b.foo
False
(Если вам интересно, почему я использовал object()
вместо, скажем, 5
это, чтобы избежать столкновения с двумя целыми другими проблемами, о которых я не хочу здесь вдаваться; по двум разным причинам полностью отдельно созданные 5
s могут оказаться тот же экземпляр числа 5
. Но полностью отдельно созданные object()
s не могут.)
Итак, почему a.foo.append(5)
в примере Алекса влияет b.foo
, а a.foo = 5
в моем - нет? Ну, попробуйте a.foo = 5
в примере Алекса, и обратите внимание , что это не влияет b.foo
там либо .
a.foo = 5
просто превращается a.foo
в имя для 5
. Это не влияет b.foo
ни на какое другое имя для старого значения, которое a.foo
использовалось для обозначения. * Немного сложно создать атрибут экземпляра, скрывающий атрибут класса, ** но как только вы это получите, ничего сложного не будет происходит здесь.
Надеюсь, теперь очевидно, почему Алекс использовал список: тот факт, что вы можете изменить список, означает, что легче показать, что две переменные называют один и тот же список, а также означает, что в реальном коде более важно знать, есть ли у вас два списка или два имени для одного и того же списка.
* Путаница для людей, пришедших с такого языка, как C ++, заключается в том, что в Python значения не хранятся в переменных. Ценности живут в мире ценностей сами по себе, переменные - это просто имена значений, а присваивание просто создает новое имя для значения. Если это помогает, думайте о каждой переменной Python как о файле, а shared_ptr<T>
не о T
.
** Некоторые люди пользуются этим, используя атрибут класса как «значение по умолчанию» для атрибута экземпляра, который экземпляры могут или не могут устанавливать. В некоторых случаях это может быть полезно, но также может сбивать с толку, поэтому будьте осторожны.