Ada dua hal yang terlibat di sini:
1. class attributes and instance attributes
2. difference between the operators + and += for lists
+
operator memanggil __add__
metode tersebut pada daftar. Ini mengambil semua elemen dari operannya dan membuat daftar baru yang berisi elemen-elemen yang menjaga urutannya.
+=
__iadd__
metode panggilan operator pada daftar. Dibutuhkan iterable dan menambahkan semua elemen dari iterable ke daftar di tempatnya. Itu tidak membuat objek daftar baru.
Di kelas foo
pernyataan self.bar += [x]
tersebut bukanlah pernyataan tugas tetapi sebenarnya diterjemahkan menjadi
self.bar.__iadd__([x]) # modifies the class attribute
yang mengubah daftar di tempat dan bertindak seperti metode daftar extend
.
Sebaliknya foo2
, di kelas , pernyataan tugas dalam init
metode
self.bar = self.bar + [x]
dapat didekonstruksi sebagai:
Instance ini tidak memiliki atribut bar
(meskipun demikian, ada atribut kelas dengan nama yang sama) sehingga ia mengakses atribut kelas bar
dan membuat daftar baru dengan menambahkannya x
. Pernyataan itu diterjemahkan menjadi:
self.bar = self.bar.__add__([x]) # bar on the lhs is the class attribute
Kemudian itu membuat atribut instance bar
dan menetapkan daftar yang baru dibuat ke dalamnya. Perhatikan bahwa bar
di rhs tugas berbeda dari bar
di lhs.
Untuk contoh kelas foo
, bar
adalah atribut kelas dan bukan atribut contoh. Karenanya setiap perubahan pada atribut kelas bar
akan tercermin untuk semua contoh.
Sebaliknya, setiap instance kelas foo2
memiliki atribut instance sendiri-sendiri bar
yang berbeda dengan atribut kelas yang bernama sama bar
.
f = foo2(4)
print f.bar # accessing the instance attribute. prints [4]
print f.__class__.bar # accessing the class attribute. prints []
Semoga ini membereskan semuanya.