Saya ingin menulis kelas khusus yang berperilaku seperti dict
- jadi, saya mewarisi dari dict
.
Pertanyaan saya, adalah: Apakah saya perlu membuat anggota pribadi dict
dalam __init__()
metode saya ?. Saya tidak mengerti maksudnya, karena saya sudah memiliki dict
perilaku jika saya hanya mewarisi dict
.
Adakah yang bisa menjelaskan mengapa sebagian besar cuplikan warisan terlihat seperti di bawah ini?
class CustomDictOne(dict):
def __init__(self):
self._mydict = {}
# other methods follow
Alih-alih yang lebih sederhana ...
class CustomDictTwo(dict):
def __init__(self):
# initialize my other stuff here ...
# other methods follow
Sebenarnya, saya rasa saya curiga jawaban dari pertanyaan tersebut adalah agar pengguna tidak dapat langsung mengakses kamus Anda (yaitu mereka harus menggunakan metode akses yang telah Anda sediakan).
Namun, bagaimana dengan operator akses array []
? Bagaimana cara menerapkan itu? Sejauh ini, saya belum melihat contoh yang menunjukkan cara menimpa []
operator.
Jadi jika []
fungsi akses tidak disediakan di kelas kustom, metode dasar yang diwarisi akan beroperasi pada kamus yang berbeda?
Saya mencoba potongan berikut untuk menguji pemahaman saya tentang warisan Python:
class myDict(dict):
def __init__(self):
self._dict = {}
def add(self, id, val):
self._dict[id] = val
md = myDict()
md.add('id', 123)
print md[id]
Saya mendapat kesalahan berikut:
KeyError: <built-in function id>
Ada apa dengan kode di atas?
Bagaimana cara mengoreksi kelas myDict
agar saya dapat menulis kode seperti ini?
md = myDict()
md['id'] = 123
[Sunting]
Saya telah mengedit contoh kode di atas untuk menghilangkan kesalahan konyol yang saya buat sebelum saya lari dari meja saya. Itu salah ketik (saya seharusnya melihatnya dari pesan kesalahan).
sumber
dict
, maka Anda harus menggunakan objek itu sendiri (menggunakansuper
) daripada hanya mendelegasikan ke instance__dict__
- yang pada dasarnya berarti Anda membuat dua dicts untuk setiap instance._dict__
yang berisi semua atribut objek (metode, bidang, dll). Anda tidak ingin main-main dengan ini kecuali jika Anda ingin menulis kode yang memodifikasi dirinya sendiri ...Seperti ini
Sekarang Anda dapat menggunakan fungsi bawaan, seperti
dict.get()
sebagaiself.get()
.Anda tidak perlu membungkus yang tersembunyi
self._dict
. Kelas Anda sudah merupakan sebuah dict.sumber
dict
tanpa memanggil konstruktornya terlebih dahulu.dict
sebenarnya berisi 2 dict-instance: Yang pertama adalah container yang diwarisi, dan yang kedua adalah dict yang memegang atribut kelas - Anda dapat menghindarinya dengan menggunakan slot .__dict__
sebenarnya hanya dibuat saat pertama kali diakses, jadi selama pengguna tidak mencoba menggunakannya, tidak masalah.__slots__
akan menyenangkan.Demi kelengkapan, berikut ini tautan ke dokumentasi yang disebutkan oleh @ björn-pollex untuk Python 2.x terbaru (2.7.7 pada saat penulisan):
Meniru Jenis Kontainer
(Maaf karena tidak menggunakan fungsi komentar, saya tidak diizinkan melakukannya dengan stackoverflow.)
sumber
Masalah dengan potongan kode ini:
... adalah metode 'tambah' Anda (... dan metode apa pun yang Anda inginkan untuk menjadi anggota kelas) harus memiliki 'diri' eksplisit yang dideklarasikan sebagai argumen pertamanya, seperti:
Untuk menerapkan operator yang kelebihan beban untuk mengakses item dengan kunci, lihat di dokumen untuk metode ajaib
__getitem__
dan__setitem__
.Perhatikan bahwa karena Python menggunakan Pengetikan Bebek, sebenarnya tidak ada alasan untuk mendapatkan kelas dict khusus dari kelas dict bahasa - tanpa mengetahui lebih banyak tentang apa yang Anda coba lakukan (misalnya, jika Anda perlu meneruskan contoh ini kelas ke beberapa kode di suatu tempat yang akan rusak kecuali
isinstance(MyDict(), dict) == True
), Anda mungkin lebih baik hanya menerapkan API yang membuat kelas Anda cukup seperti dikt dan berhenti di sana.sumber
Berikut solusi alternatifnya:
sumber
Saya benar-benar tidak melihat jawaban yang benar untuk ini di mana pun
Yang harus Anda lakukan hanyalah mendefinisikan milik Anda sendiri
__init__
- hanya itu yang ada juga.Contoh lain (sedikit lebih kompleks):
Contoh terakhir ini berguna saat Anda ingin menyematkan beberapa jenis logika.
Pokoknya ... singkatnya
class GiveYourClassAName(dict)
sudah cukup untuk membuat kelas Anda bertingkah seperti dikt. Operasi dict apa pun yang Anda lakukanself
akan menjadi seperti dict biasa.sumber
Ini adalah solusi terbaik saya. Saya menggunakan ini berkali-kali.
Anda bisa menggunakan seperti:
sumber
Jangan pernah mewarisi dari diktik bawaan Python! Misalnya
update
metode yang tidak akan digunakan__setitem__
, mereka melakukan banyak hal untuk pengoptimalan. Gunakan UserDict.sumber