Pertama-tama A.__dict__.__dict__
berbeda dari A.__dict__['__dict__']
, dan yang pertama tidak ada. Yang terakhir adalah __dict__
atribut yang dimiliki oleh instance kelas. Ini adalah objek deskriptor yang mengembalikan kamus internal atribut untuk instance tertentu. Singkatnya, __dict__
atribut suatu objek tidak dapat disimpan dalam objek __dict__
, jadi itu diakses melalui deskriptor yang ditentukan di kelas.
Untuk memahami ini, Anda harus membaca dokumentasi protokol deskriptor .
Versi singkatnya:
- Untuk instance kelas
A
, akses ke instance.__dict__
disediakan oleh A.__dict__['__dict__']
yang sama dengan vars(A)['__dict__']
.
- Untuk kelas A, akses ke
A.__dict__
disediakan oleh type.__dict__['__dict__']
(secara teori) yang sama dengan vars(type)['__dict__']
.
Versi panjang:
Baik kelas maupun objek menyediakan akses ke atribut baik melalui operator atribut (diimplementasikan melalui kelas atau metaclass __getattribute__
), dan __dict__
atribut / protokol yang digunakan oleh vars(ob)
.
Untuk objek normal, __dict__
objek membuat objek terpisah dict
, yang menyimpan atribut, dan __getattribute__
pertama kali mencoba mengaksesnya dan mendapatkan atribut dari sana (sebelum mencoba mencari atribut di kelas dengan memanfaatkan protokol deskriptor, dan sebelum memanggil __getattr__
). The __dict__
descriptor pada kelas mengimplementasikan akses ke kamus ini.
x.name
setara dengan mencoba mereka dalam rangka: x.__dict__['name']
, type(x).name.__get__(x, type(x))
,type(x).name
x.__dict__
melakukan hal yang sama tetapi melewatkan yang pertama karena alasan yang jelas
Seperti tidak mungkin untuk __dict__
dari instance
untuk disimpan dalam __dict__
instance, itu diakses melalui protokol deskriptor langsung sebaliknya, dan disimpan dalam bidang khusus dalam hal ini.
Skenario serupa berlaku untuk kelas, meskipun mereka __dict__
adalah objek proxy khusus yang berpura-pura menjadi kamus (tetapi mungkin tidak secara internal), dan tidak memungkinkan Anda untuk mengubahnya atau menggantinya dengan yang lain. Proksi ini memungkinkan Anda, di antara yang lainnya, untuk mengakses atribut kelas yang khusus untuk itu, dan tidak ditentukan di salah satu basisnya.
Secara default, vars(cls)
kelas kosong membawa tiga deskriptor - __dict__
untuk menyimpan atribut instance, __weakref__
yang digunakan secara internal oleh weakref
, dan docstring kelas. Dua yang pertama mungkin hilang jika Anda menentukan __slots__
. Maka Anda tidak akan memiliki __dict__
dan __weakref__
atribut, tetapi Anda akan memiliki atribut kelas tunggal untuk setiap slot. Atribut instance tidak akan disimpan dalam kamus, dan akses ke sana akan disediakan oleh deskriptor masing-masing di kelas.
Dan terakhir, ketidakkonsistenan yang A.__dict__
berbeda dari A.__dict__['__dict__']
adalah karena atribut __dict__
, dengan pengecualian, tidak pernah dicari vars(A)
, jadi apa yang benar karena itu tidak benar untuk hampir semua atribut lain yang Anda gunakan. Misalnya, A.__weakref__
sama saja dengan A.__dict__['__weakref__']
. Jika ketidakkonsistenan ini tidak ada, penggunaan A.__dict__
tidak akan berhasil, dan Anda harus selalu menggunakannya vars(A)
.
ive
. Setidaknya itu akan membuat ini menjadiA.__dict__['ive']
pertanyaan lagi ;) Saya akan melihat diri saya keluar