Karena orang-orang di komentar di sini dan di dua pertanyaan lain yang ditandai sebagai dups semuanya tampak bingung tentang hal ini dengan cara yang sama, saya pikir ada baiknya menambahkan jawaban tambahan di atas jawaban Alex Coventry .
Fakta bahwa Alex memberikan nilai dari tipe yang bisa berubah, seperti daftar, tidak ada hubungannya dengan apakah semuanya dibagikan atau tidak. Kita dapat melihat ini dengan id
fungsi atau is
operator:
>>> 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
(Jika Anda bertanya-tanya mengapa saya menggunakan object()
alih-alih, katakanlah, 5
itu untuk menghindari dua masalah lain yang sama sekali tidak ingin saya bahas di sini; karena dua alasan berbeda, sepenuhnya diciptakan secara terpisah 5
dapat berakhir menjadi contoh nomor yang sama 5
. Tapi seluruhnya dibuat secara terpisah object()
tidak bisa.)
Jadi, mengapa hal itu a.foo.append(5)
dalam contoh Alex memengaruhi b.foo
, tetapi a.foo = 5
dalam contoh saya tidak? Nah, coba a.foo = 5
dalam contoh Alex, dan perhatikan bahwa itu tidak mempengaruhi di b.foo
sana juga .
a.foo = 5
hanya membuat a.foo
menjadi nama untuk 5
. Itu tidak mempengaruhi b.foo
, atau nama lain untuk nilai lama yang a.foo
digunakan untuk merujuk. * Agak sulit bahwa kita membuat atribut instance yang menyembunyikan atribut kelas, ** tapi begitu Anda mendapatkannya, tidak ada yang rumit adalah terjadi di sini.
Mudah-mudahan sekarang jelas mengapa Alex menggunakan daftar: fakta bahwa Anda dapat bermutasi daftar berarti lebih mudah untuk menunjukkan bahwa dua variabel nama daftar yang sama, dan juga berarti lebih penting dalam kode kehidupan nyata untuk mengetahui apakah Anda memiliki dua daftar atau dua nama untuk daftar yang sama.
* Kebingungan bagi orang-orang yang berasal dari bahasa seperti C ++ adalah bahwa dalam Python, nilai tidak disimpan dalam variabel. Nilai hidup di tanah nilai, sendiri, variabel hanya nama untuk nilai, dan tugas hanya membuat nama baru untuk nilai. Jika ini membantu, pikirkan setiap variabel Python sebagai shared_ptr<T>
bukan T
.
** Beberapa orang memanfaatkan ini dengan menggunakan atribut kelas sebagai "nilai default" untuk atribut instance yang instans mungkin atau mungkin tidak disetel. Ini bisa berguna dalam beberapa kasus, tetapi juga bisa membingungkan, jadi berhati-hatilah.