Saya sedang mencari cara yang elegan untuk mendapatkan data menggunakan akses atribut pada dict dengan beberapa dict dan daftar bersarang (yaitu sintaks objek gaya javascript).
Sebagai contoh:
>>> d = {'a': 1, 'b': {'c': 2}, 'd': ["hi", {'foo': "bar"}]}
Harus dapat diakses dengan cara ini:
>>> x = dict2obj(d)
>>> x.a
1
>>> x.b.c
2
>>> x.d[1].foo
bar
Saya pikir, ini tidak mungkin tanpa rekursi, tetapi apa cara yang bagus untuk mendapatkan gaya objek untuk dikte?
python
object
dictionary
Marc
sumber
sumber
from_
daripada_from
menurut PEP 8 .getattr(x, 'from')
alih-alih mengganti nama atribut.d1.b.c
), saya pikir jelas Anda harus menggunakan sesuatu dari perpustakaan, mis. Namupilih dari koleksi , seperti jawaban ini menyarankan, .. .Jawaban:
Pembaruan: Dalam Python 2.6 dan seterusnya, pertimbangkan apakah
namedtuple
struktur data sesuai dengan kebutuhan Anda:Alternatif (isi jawaban asli) adalah:
Kemudian, Anda dapat menggunakan:
sumber
Struct
dari kamus bersarang, tetapi secara umum jenis nilai bisa apa saja. Kunci dibatasi agar sesuai untuk slot objekargparse.Namespace
(yang juga telah ditetapkan__eq__
,__ne__
,__contains__
).sumber
if isinstance(b, (list, tuple)):
obj
kelas mewarisi dariargparse.Namespace
untuk fitur tambahan seperti representasi string yang dapat dibaca.Anehnya, belum ada yang menyebut Bunch . Perpustakaan ini secara eksklusif dimaksudkan untuk menyediakan akses gaya atribut ke objek-objek dict dan melakukan persis apa yang diinginkan OP. Demonstrasi:
Pustaka Python 3 tersedia di https://github.com/Infinidat/munch - Kredit diberikan ke codyzu
sumber
kemudian tambahkan rekursi untuk ini dan Anda selesai.
edit ini bagaimana saya menerapkannya:
sumber
top_instance = top()
dan mengembalikannya ke tempat Anda kembalitop
?x
danx.b
yang kembali jelek<class '__main__.new'>
Ada penolong koleksi bernama
namedtuple
, yang dapat melakukan ini untuk Anda:sumber
Dapat digunakan dengan urutan / dikt / struktur nilai kedalaman apa pun.
sumber
def __repr__(self): return '{%s}' % str(', '.join("'%s': %s" % (k, repr(v)) for (k, v) in self.__dict__.iteritems()))
.items()
bukan.iteritems()
di baris 4. (Fungsi ini diganti namanya, tetapi tidak sama )Mengambil apa yang saya rasakan adalah aspek terbaik dari contoh-contoh sebelumnya, inilah yang saya buat:
sumber
def __init__(self, dct): for k, v in dct.iteritems(): setattr(self, k, isinstance(v, dict) and self.__class__(v) or v)
yang juga menghilangkan panggilan eksplisit keStruct
isinstance(v, dict)
cek akan lebih baik sebagaiisinstance(v, collections.Mapping)
sehingga dapat menangani masa depan dict-seperti halJika dict Anda berasal
json.loads()
, Anda dapat mengubahnya menjadi objek alih-alih (bukan dict) dalam satu baris:Lihat juga Cara mengonversi data JSON menjadi objek Python .
sumber
.loads
jika Anda memiliki objek JSON besarJika Anda ingin mengakses kunci dict sebagai objek (atau sebagai dict untuk kunci yang sulit), lakukan secara rekursif, dan juga dapat memperbarui dict yang asli, Anda dapat melakukan:
Contoh penggunaan:
sumber
sumber
Saya akhirnya mencoba KEDUA AttrDict dan Bunchperpustakaan dan menemukan mereka terlalu 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 masing-masing dari 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,
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
x.__dict__.update(d)
harus baik-baik saja.sumber
__dict__
: cobaobject().__dict__
dan Anda akan dapatkanAttributeError: 'object' object has no attribute '__dict__'
Anda dapat memanfaatkan
json
modul perpustakaan standar dengan kait objek khusus :Contoh penggunaan:
Dan tidak sepenuhnya hanya-baca seperti itu
namedtuple
, yaitu Anda dapat mengubah nilai - bukan struktur:sumber
json.JSONEncoder
danobject_hook
.Ini harus Anda mulai:
Belum berfungsi untuk daftar. Anda harus membungkus daftar dalam Daftar Pengguna dan membebani
__getitem__
untuk membungkus dicts.sumber
if isinstance(d, list)
klausa dariAnon
jawaban.Saya tahu sudah ada banyak jawaban di sini sudah dan saya terlambat ke pesta tetapi metode ini akan secara rekursif dan 'di tempat' mengkonversi kamus ke struktur seperti objek ... Bekerja di 3.xx
sumber
sumber
Biarkan saya menjelaskan solusi yang saya hampir gunakan beberapa waktu lalu. Tapi pertama-tama, alasan saya tidak diilustrasikan oleh fakta bahwa kode berikut:
memberikan kesalahan ini:
Karena "dari" adalah kata kunci Python, ada kunci kamus tertentu yang tidak dapat Anda izinkan.
Sekarang solusi saya memungkinkan akses ke item kamus dengan menggunakan nama mereka secara langsung. Tetapi juga memungkinkan Anda untuk menggunakan "semantik kamus". Berikut adalah kode dengan contoh penggunaan:
sumber
Tanya Jawab Lama, tapi saya ingin bicara lebih banyak. Sepertinya tidak ada yang bicara tentang dict rekursif. Ini kode saya:
sumber
Ingin mengunggah versi saya dari paradigma kecil ini.
Ini mempertahankan atribut untuk tipe yang diimpor ke dalam kelas. Satu-satunya kekhawatiran saya adalah menimpa metode dari dalam kamus parsing Anda. Tetapi sebaliknya terlihat solid!
sumber
df.a
tidak berfungsi.Ini juga berfungsi dengan baik
sumber
Berikut ini cara lain untuk mengimplementasikan saran asli SilentGhost:
sumber
Saya menemukan case yang saya butuhkan untuk secara rekursif mengubah daftar dicts ke daftar objek, jadi berdasarkan potongan Roberto di sini apa yang berhasil bagi saya:
Perhatikan bahwa setiap tuple akan dikonversi ke daftar yang setara, karena alasan yang jelas.
Semoga ini bisa membantu seseorang seperti halnya semua jawaban Anda untuk saya, kawan.
sumber
Bagaimana dengan hanya menempatkan Anda
dict
ke__dict__
objek kosong?Tentu saja ini gagal pada contoh dict Anda kecuali jika Anda menjalankan dict tersebut secara rekursif:
Dan elemen daftar contoh Anda mungkin dimaksudkan untuk menjadi
Mapping
, daftar pasangan (kunci, nilai) seperti ini:sumber
Inilah implementasi lain:
[Sunting] Melewatkan sedikit tentang juga menangani dicts dalam daftar, bukan hanya dicts lainnya. Menambahkan perbaikan.
sumber
Pemakaian:
sumber
Bagaimana dengan ini:
Ini kemudian dapat digunakan seperti ini:
sumber
Saya pikir sebuah dikt terdiri dari angka, string, dan dikt cukup banyak waktu. Jadi saya mengabaikan situasi yang tupel, daftar, dan jenis lainnya yang tidak muncul dalam dimensi akhir suatu dikt.
Mempertimbangkan pewarisan, dikombinasikan dengan rekursi, ia menyelesaikan masalah pencetakan dengan mudah dan juga menyediakan dua cara untuk meminta data, satu cara untuk mengedit data.
Lihat contoh di bawah ini, sebuah dikt yang menggambarkan beberapa informasi tentang siswa:
Hasil:
sumber
Biasanya Anda ingin mencerminkan hierarki dikt ke dalam objek Anda tetapi tidak daftar atau tupel yang biasanya di tingkat terendah. Jadi ini adalah bagaimana saya melakukan ini:
Jadi kami lakukan:
dan dapatkan:
x.b.b1.x
1x.c
['hai', 'bar']sumber
Kamus saya dalam format ini:
Seperti dapat dilihat, saya memiliki kamus dan daftar dikte bersarang . Ini karena addr_bk didekodekan dari data buffer protokol yang dikonversi ke python dict menggunakan lwpb.codec. Ada bidang opsional (mis. Email => di mana kunci mungkin tidak tersedia) dan bidang berulang (mis. Telepon => dikonversi ke daftar dict).
Saya mencoba semua solusi yang diusulkan di atas. Beberapa tidak menangani kamus bersarang dengan baik. Orang lain tidak dapat mencetak detail objek dengan mudah.
Hanya solusinya, dict2obj (dict) oleh Dawie Strauss, yang paling berhasil.
Saya telah sedikit meningkatkannya untuk menangani ketika kunci tidak dapat ditemukan:
Lalu, saya mengujinya dengan:
sumber
Membangun jawaban saya untuk " python: Bagaimana cara menambahkan properti ke kelas secara dinamis? ":
Anda memanggil
makedata
kamus yang ingin Anda konversi, atau mungkintrydata
tergantung pada apa yang Anda harapkan sebagai input, dan itu memuntahkan objek data.Catatan:
trydata
jika Anda membutuhkan lebih banyak fungsi.x.a = {}
atau serupa.sumber