Saya ingin mengganti akses ke satu variabel di kelas, tetapi mengembalikan semua variabel secara normal. Bagaimana saya melakukannya __getattribute__
?
Saya mencoba yang berikut (yang juga harus menggambarkan apa yang saya coba lakukan) tetapi saya mendapatkan kesalahan rekursi:
class D(object):
def __init__(self):
self.test=20
self.test2=21
def __getattribute__(self,name):
if name=='test':
return 0.
else:
return self.__dict__[name]
>>> print D().test
0.0
>>> print D().test2
...
RuntimeError: maximum recursion depth exceeded in cmp
super(D, self).__getattribute__(name)
super().__getattribute__(name)
Python 3.Sebenarnya, saya yakin Anda ingin menggunakan
__getattr__
metode khusus sebagai gantinya.Kutipan dari dokumen Python:
Catatan: agar ini berfungsi, instance tidak boleh memiliki
test
atribut, jadi barisself.test=20
harus dihapus.sumber
__getattr__
untuktest
tidak akan berguna, karena akan selalu menemukannya "di tempat biasa".Referensi bahasa Python:
Berarti:
Anda memanggil atribut yang disebut
__dict__
. Karena itu adalah atribut,__getattribute__
dipanggil untuk mencari__dict__
panggilan__getattribute__
mana yang memanggil ... yada yada yadaMenggunakan kelas dasar
__getattribute__
membantu menemukan atribut sebenarnya.sumber
Anda yakin ingin menggunakan
__getattribute__
? Apa yang sebenarnya ingin Anda capai?Cara termudah untuk melakukan apa yang Anda minta adalah:
atau:
Edit: Perhatikan bahwa sebuah instance
D
akan memiliki nilai yang berbedatest
dalam setiap kasus. Dalam kasus pertamad.test
akan menjadi 20, dalam kasus kedua akan menjadi 0. Saya akan menyerahkan kepada Anda untuk mencari tahu mengapa.Edit2: Greg menunjukkan bahwa contoh 2 akan gagal karena propertinya hanya baca dan
__init__
metode mencoba menyetelnya ke 20. Contoh yang lebih lengkap untuk itu adalah:Jelas, sebagai kelas ini hampir seluruhnya tidak berguna, tetapi ini memberi Anda ide untuk melanjutkan.
sumber
Ini adalah versi yang lebih andal:
Ini panggilan __ getAttribute __ metode dari kelas induk, akhirnya jatuh kembali ke objek. __ getattribute __ jika leluhur lain tidak menimpanya .
sumber
Ini dipanggil sebelum pencarian titik-titik normal. Jika itu timbul
AttributeError
, maka kita panggil__getattr__
.Penggunaan metode ini agak jarang. Hanya ada dua definisi di pustaka standar:
Praktek terbaik
Cara yang tepat untuk mengontrol akses secara terprogram ke satu atribut adalah dengan
property
. KelasD
harus ditulis sebagai berikut (dengan setter dan deleter secara opsional untuk mereplikasi perilaku yang dimaksudkan):Dan penggunaan:
Properti adalah deskriptor data, jadi ini adalah hal pertama yang dicari dalam algoritme pencarian titik-titik normal.
Opsi untuk
__getattribute__
Anda memiliki beberapa opsi jika Anda benar-benar perlu mengimplementasikan pencarian untuk setiap atribut melalui
__getattribute__
.AttributeError
, menyebabkan__getattr__
dipanggil (jika diterapkan)super
untuk memanggil orang tua (mungkinobject
implementasi )__getattr__
Sebagai contoh:
Apa yang awalnya Anda inginkan.
Dan contoh ini menunjukkan bagaimana Anda dapat melakukan apa yang awalnya Anda inginkan:
Dan akan berperilaku seperti ini:
Peninjauan kode
Kode Anda dengan komentar. Anda memiliki pencarian titik-titik pada diri sendiri
__getattribute__
. Inilah mengapa Anda mendapatkan kesalahan rekursi. Anda dapat memeriksa apakah namanya"__dict__"
dan digunakansuper
untuk mengatasinya, tetapi itu tidak mencakup__slots__
. Saya akan serahkan itu sebagai latihan kepada pembaca.sumber