Bagaimana cara membuat anggota kamus Python dapat diakses melalui titik "."?
Misalnya, alih-alih menulis mydict['val']
, saya ingin menulis mydict.val
.
Juga saya ingin mengakses dicts bersarang dengan cara ini. Sebagai contoh
mydict.mydict2.val
akan merujuk
mydict = { 'mydict2': { 'val': ... } }
python
dictionary
syntax
nested
bodacydo
sumber
sumber
d[a][b][c]
digantikan olehd[a, b, c]
.{"my.key":"value"}
? Atau ketika kuncinya adalah kata kunci, seperti "dari"? Saya telah mempertimbangkannya beberapa kali, dan ini lebih banyak masalah dan pemecahan masalah daripada manfaat yang dirasakan.Jawaban:
Anda dapat melakukannya menggunakan kelas yang baru saja saya buat. Dengan kelas ini Anda dapat menggunakan
Map
objek seperti kamus lain (termasuk serialisasi json) atau dengan notasi titik. Saya berharap dapat membantu Anda:Contoh penggunaan:
sumber
.iteritems()
ke.items()
AttributeError
jika atribut tidak ada. Sebaliknya itu akan kembaliNone
.self.update(*args,**kwargs)
. Anda juga bisa menambahkan__missing__(self,key): value=self[key]= type(self)(); return value
. Kemudian Anda dapat menambahkan entri yang hilang menggunakan notasi titik. Jika Anda ingin dipilih, Anda dapat menambahkan__getstate__
dan__setstate__
hasattr(Map, 'anystring') is true. which means the hasattr would always return True due to overriding
__getattr__`Saya selalu menyimpan ini di dalam file util. Anda dapat menggunakannya sebagai mixin di kelas Anda sendiri juga.
sumber
d = {'foo': {'bar': 'baz'}}; d = dotdict(d); d.foo.bar
melempar kesalahan atribut, tetapid.foo
berfungsi dengan baik.python class DotDict(dict): """dot.notation access to dictionary attributes""" def __getattr__(*args): val = dict.get(*args) return DotDict(val) if type(val) is dict else val __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__
get
memang ide yang buruk karena itu akan kembaliNone
bukannya meningkatkan kesalahan untuk barang yang hilang ...Instal
dotmap
viapip
Itu melakukan semua yang Anda ingin lakukan dan subclass
dict
, sehingga beroperasi seperti kamus normal:Selain itu, Anda dapat mengubahnya ke dan dari
dict
objek:Ini berarti bahwa jika sesuatu yang ingin Anda akses sudah dalam
dict
bentuk, Anda dapat mengubahnya menjadiDotMap
akses yang mudah:Akhirnya, secara otomatis membuat
DotMap
instance anak baru sehingga Anda dapat melakukan hal-hal seperti ini:Perbandingan dengan Bunch
Pengungkapan penuh: Saya adalah pencipta DotMap . Saya membuatnya karena
Bunch
tidak memiliki fitur-fitur iniDotMap
pembuatan anak otomatis , yang menghemat waktu dan membuat kode lebih bersih ketika Anda memiliki banyak hierarkidict
dan secara rekursif mengkonversi semuadict
instance anakDotMap
sumber
{"test.foo": "bar"}
dapat diakses melaluimymap.test.foo
Itu akan fantastis. Dibutuhkan beberapa regresi untuk mengubah peta datar menjadi peta yang dalam kemudian menerapkan DotMap ke dalamnya, tetapi itu sangat berharga!DotMap
dengan autocomplete yang terbaik. Saya menggunakan Teks Sublim, yang secara otomatis melengkapi kata kunci yang diketik sebelumnya.**kwargs
atauc = {**a, **b}
. Bahkan, gagal diam-diam, itu berperilaku seperti kamus kosong saat mengekstraksi.m = DotMap(); m.a = 2; m.b = 3; print('{a} {b}'.format(**m));
dan saya mendapatkan yang diharapkan2 3
. Jika Anda memiliki kasus rusak yang terbukti berhasildict()
tetapi tidakDotMap()
, kirimkan kode Anda ke tab Masalah di GitHub.Berasal dari dikt dan dan mengimplementasikan
__getattr__
dan__setattr__
.Atau Anda dapat menggunakan Bunch yang sangat mirip.
Saya tidak berpikir itu mungkin untuk monkeypatch kelas dict bawaan.
sumber
Kain memiliki implementasi yang sangat bagus, minimal . Memperluas itu untuk memungkinkan akses bersarang, kita dapat menggunakan
defaultdict
, dan hasilnya terlihat seperti ini:Manfaatkan sebagai berikut:
Itu menguraikan sedikit pada jawaban Kugel tentang "Berasal dari dikt dan dan mengimplementasikan
__getattr__
dan__setattr__
". Sekarang kamu tahu caranya!sumber
dotdict
yang memungkinkan untuk mengonversidict
objek yang ada secara rekursif: gist.github.com/miku/…Saya mencoba ini:
Anda dapat mencoba
__getattribute__
juga.buat setiap dict jenis dotdict akan cukup bagus, jika Anda ingin init ini dari multi-layer dict, coba implementasikan
__init__
juga.sumber
def docdict(name):
sebelumnya dan kemudian `if isinstance (name, dict): return DotDict (name) returnclass dotdict(dict): def __getattr__(self, name): if name not in self: return None elif type(self[name]) is dict: return JsonDot(self[name]) else: return self[name]
Jangan. Akses atribut dan pengindeksan adalah hal-hal terpisah dalam Python, dan Anda seharusnya tidak ingin mereka melakukan hal yang sama. Buat kelas (mungkin yang dibuat oleh
namedtuple
) jika Anda memiliki sesuatu yang harus memiliki atribut yang dapat diakses dan menggunakan[]
notasi untuk mendapatkan item dari dict.sumber
.
daripada[]
mengakses struktur data yang rumit dalam templat Mako.Jika Anda ingin menggunakan kamus Anda yang dimodifikasi, Anda perlu menambahkan beberapa metode status ke jawaban di atas:
sumber
__getattr__ = dict.get
Membangun jawaban Kugel dan mempertimbangkan kata-kata peringatan dari Mike Graham, bagaimana jika kita membuat bungkus?
sumber
Gunakan
SimpleNamespace
:sumber
Saya suka Munch dan memberikan banyak opsi berguna di atas akses dot.
sumber
Saya baru-baru ini menemukan ' Box perpustakaan ' ' yang melakukan hal yang sama.
Perintah instalasi:
pip install python-box
Contoh:
Saya menemukan itu lebih efektif daripada perpustakaan lain yang ada seperti dotmap, yang menghasilkan kesalahan rekursi python ketika Anda memiliki dicts bersarang besar.
tautan ke perpustakaan dan detail: https://pypi.org/project/python-box/
sumber
Gunakan
__getattr__
, sangat sederhana, bekerja di Python 3.4.3Keluaran:
sumber
Bahasa itu sendiri tidak mendukung ini, tetapi kadang-kadang ini masih merupakan persyaratan yang berguna. Selain resep Bunch, Anda juga dapat menulis metode kecil yang dapat mengakses kamus menggunakan string bertitik:
yang akan mendukung sesuatu seperti ini:
sumber
Untuk membangun berdasarkan jawaban epool, versi ini memungkinkan Anda untuk mengakses setiap dikt dalam melalui operator titik:
Misalnya,
foo.bar.baz[1].baba
kembali"loo"
.sumber
iteritems()
denganitems()
danxrange()
denganrange()
Jika seseorang memutuskan untuk secara permanen mengkonversi itu
dict
ke objek ini harus dilakukan. Anda dapat membuat objek sekali pakai sebelum mengakses.sumber
Saya akhirnya mencoba KEDUA AttrDict dan Bunchperpustakaan dan menemukan mereka menjadi cara lambat untuk saya gunakan. Setelah seorang teman dan saya melihatnya, kami menemukan bahwa metode utama untuk menulis perpustakaan ini menghasilkan perpustakaan secara agresif berulang melalui objek bersarang dan membuat salinan dari objek kamus di seluruh. Dengan mengingat hal ini, kami membuat dua perubahan penting. 1) Kami membuat atribut lazy-loaded 2) alih-alih membuat salinan objek kamus, kami membuat salinan objek proxy yang ringan. Ini adalah implementasi terakhir. Peningkatan kinerja menggunakan kode ini luar biasa. Saat menggunakan AttrDict atau Bunch, dua perpustakaan ini saja menghabiskan 1/2 dan 1/3 waktu permintaan saya (apa !?). Kode ini mengurangi waktu itu menjadi hampir tidak ada (di suatu tempat di kisaran 0,5 ms). Ini tentu saja tergantung pada kebutuhan Anda, tetapi jika Anda menggunakan fungsi ini sedikit dalam kode Anda,
Lihat implementasi asli di sini oleh https://stackoverflow.com/users/704327/michael-merickel .
Hal lain yang perlu diperhatikan, adalah implementasi ini cukup sederhana dan tidak menerapkan semua metode yang mungkin Anda butuhkan. Anda harus menulis yang diperlukan pada objek DictProxy atau ListProxy.
sumber
Saya ingin melemparkan solusi saya sendiri ke atas ring:
https://github.com/skorokithakis/jsane
Ini memungkinkan Anda untuk mengurai JSON menjadi sesuatu yang dapat Anda akses
with.attribute.lookups.like.this.r()
, sebagian besar karena saya belum melihat jawaban ini sebelum mulai mengerjakannya.sumber
KeyError
adalah salah satunya, Ketika seseorang mengakses kunci yang tidak ada yang harus dilakukan hanyalah mengembalikanNone
mirip dengan perilaku JS. Saya penggemar autovivifikasi baik untuk membaca dan menulis. Perpustakaan Anda paling dekat dengan yang ideal.Bukan jawaban langsung untuk pertanyaan OP, tetapi diilhami oleh dan mungkin bermanfaat bagi sebagian orang .. Saya telah membuat solusi berbasis objek menggunakan internal
__dict__
(Sama sekali tidak dioptimalkan kode)sumber
Salah satu cara sederhana untuk mendapatkan akses dot (tetapi bukan akses array), adalah dengan menggunakan objek biasa dalam Python. Seperti ini:
... dan gunakan seperti ini:
... untuk mengubahnya menjadi dict:
sumber
Solusi ini merupakan penyempurnaan dari yang ditawarkan oleh epool untuk mengatasi persyaratan OP untuk mengakses dicts bersarang secara konsisten. Solusi oleh epool tidak memungkinkan untuk mengakses dicts bersarang.
Dengan kelas ini, satu sekarang dapat melakukan sesuatu seperti:
A.B.C.D
.sumber
Ini juga berfungsi dengan dikte bersarang dan memastikan bahwa dikte yang ditambahkan nanti berperilaku sama:
sumber
Jawaban dari @ derek73 sangat rapi, tetapi tidak dapat diasamkan atau disalin, dan kembali
None
untuk kunci yang hilang. Kode di bawah ini memperbaiki ini.Sunting: Saya tidak melihat jawaban di atas yang membahas titik yang sama persis (terbalik). Saya meninggalkan jawabannya di sini untuk referensi.
sumber
Suatu jenis solusi yang halus
sumber