Saya sedikit bingung dengan kode berikut:
d = {'x': 1, 'y': 2, 'z': 3}
for key in d:
print key, 'corresponds to', d[key]
Apa yang saya don't mengerti adalah kunci
porsi. Bagaimana Python mengakui bahwa itu hanya perlu membaca kunci dari kamus? Adalah kunci
kata khusus dalam Python? Atau itu hanya sebuah variabel?
kunci
hanya nama variabel.
for key in d:
hanya akan loop melalui tombol di kamus, daripada kunci dan nilai-nilai. Loop di atas kedua kunci dan nilai yang anda dapat menggunakan berikut:
Untuk Python Versi 2.x:
for key, value in d.iteritems():
Untuk Python 3.x:
for key, value in d.items():
Untuk menguji diri anda, mengubah kata kunci
untuk kotoran
.
Untuk Python 3.x, iteritems()
telah digantikan dengan hanya item()
, yang mengembalikan satu set-seperti pandangan yang didukung oleh dict, seperti iteritems()
tetapi bahkan lebih baik.
Ini juga tersedia di 2.7 sebagai viewitems()
.
Operasi item()
akan bekerja untuk kedua 2 dan 3, tapi dalam 2 itu akan kembali daftar kamus's (key, value)
pasangan, yang tidak akan mencerminkan perubahan dict yang terjadi setelah item()
call. Jika anda ingin 2.x perilaku dalam 3.x, anda dapat memanggil daftar(d.item())
.
It's tidak bahwa kunci adalah kata khusus, tapi itu kamus menerapkan iterator protokol. Anda bisa melakukan ini di kelas anda, misalnya melihat pertanyaan untuk bagaimana membangun class iterator.
Dalam kasus kamus, it's dilaksanakan di tingkat C. Rincian tersedia di PEP 234. Secara khusus, bagian yang berjudul "Kamus Iterator":
- Kamus menerapkan tp_iter slot yang mengembalikan aplikasi yang efisien iterator yang iterates atas tombol dari kamus. [...] Ini berarti bahwa kita dapat menulis
untuk k di dict: ...
yang setara dengan, tapi jauh lebih cepat dari
untuk k di dict.kunci-kunci(): ...
asalkan pembatasan modifikasi kamus (baik dengan loop atau oleh thread lain) tidak melanggar.
- Tambahkan metode untuk kamus yang kembali berbagai jenis iterator secara eksplisit:
untuk kunci di dict.iterkeys(): ...
untuk nilai di dict.itervalues(): ...
untuk kunci, nilai di dict.iteritems(): ...
Ini berarti bahwa
untuk x di dict
adalah kependekan darix di dict.iterkeys()
.
Di Python 3, dict.iterkeys()
, dict.itervalues()
dan dict.iteritems()
adalah tidak lagi didukung. Gunakan dict.kunci-kunci()
, dict.nilai-nilai()
dan dict.item()
sebagai gantinya.
Iterasi yang dict
iterates melalui tombol dalam urutan tertentu, seperti yang anda bisa lihat di sini:
Edit: (Ini tidak ada lagi kasus di Python3.6, tetapi perhatikan bahwa's tidak dijamin perilaku yang belum)
>>> d = {'x': 1, 'y': 2, 'z': 3}
>>> list(d)
['y', 'x', 'z']
>>> d.keys()
['y', 'x', 'z']
Untuk contoh anda, itu adalah ide yang baik untuk menggunakan dict.item()
:
>>> d.items()
[('y', 2), ('x', 1), ('z', 3)]
Ini memberi anda daftar tupel. Ketika anda loop di atas mereka seperti ini, masing-masing tuple adalah membongkar ke k
dan v
secara otomatis:
for k,v in d.items():
print(k, 'corresponds to', v)
Menggunakan k
dan v
sebagai nama variabel ketika perulangan di atas dict
cukup umum jika tubuh loop hanya beberapa baris. Untuk lebih rumit loop mungkin ide yang baik untuk menggunakan lebih deskriptif nama:
for letter, number in d.items():
print(letter, 'corresponds to', number)
It's merupakan ide yang baik untuk mendapatkan ke dalam kebiasaan menggunakan format string:
for letter, number in d.items():
print('{0} corresponds to {1}'.format(letter, number))
kunci
hanyalah sebuah variabel.
Untuk Python2.X:
d = {'x': 1, 'y': 2, 'z': 3}
for my_var in d:
print my_var, 'corresponds to', d[my_var]
... atau lebih baik,
d = {'x': 1, 'y': 2, 'z': 3}
for the_key, the_value in d.iteritems():
print the_key, 'corresponds to', the_value
Untuk Python3.X:
d = {'x': 1, 'y': 2, 'z': 3}
for the_key, the_value in d.items():
print(the_key, 'corresponds to', the_value)
Ketika anda iterate melalui kamus menggunakan for .. in ..
-sintaks, selalu iterates di atas tombol (nilai-nilai yang dapat diakses menggunakan kamus[key]
).
Untuk iterate atas pasangan kunci-nilai, dalam Python 2 menggunakan untuk k,v s.iteritems()
, dan di Python 3 untuk k,v s.item()
.
Ini adalah yang sangat umum perulangan idiom. dalam
adalah operator. Ketika menggunakan untuk kunci di dict
dan ketika itu harus untuk kunci di dict.kunci-kunci()
lihat David Goodger's Idiomatik Python artikel (diarsipkan copy).
Saya telah menggunakan kasus di mana saya harus iterate melalui dict untuk mendapatkan kunci, pasangan nilai, juga indeks yang menunjukkan di mana aku berada. Ini adalah bagaimana saya melakukannya:
d = {'x': 1, 'y': 2, 'z': 3}
for i, (key, value) in enumerate(d.items()):
print(i, key, value)
Perhatikan bahwa tanda kurung di sekitar kunci, nilai penting, tanpa tanda kurung, anda mendapatkan ValueError "tidak cukup nilai untuk membongkar".
Iterasi kamus menggunakan 'untuk' loop
a = {'x': 1, 'y': 2, 'z': 3} untuk kunci di d: ...
Bagaimana Python mengakui bahwa itu hanya perlu membaca kunci dari kamus? Adalah kunci kata khusus dalam Python? Atau itu hanya sebuah variabel?
It's tidak hanya untuk
loop. Kata penting di sini adalah "iterasi".
Kamus adalah sebuah pemetaan kunci untuk nilai-nilai:
d = {'x': 1, 'y': 2, 'z': 3}
Setiap kali kita iterate atas itu, kita iterate atas tombol. Nama variabel kunci
ini hanya dimaksudkan untuk menjadi deskriptif - dan hal ini cukup tepat untuk tujuan tersebut.
Hal ini terjadi dalam daftar pemahaman:
>>> [k for k in d]
['x', 'y', 'z']
Hal itu terjadi ketika kami melewati kamus untuk daftar (atau lain jenis koleksi benda):
>>> list(d)
['x', 'y', 'z']
Cara Python iterates adalah, dalam konteks di mana perlu, itu panggilan __iter__
metode dari objek (dalam hal ini adalah kamus) yang mengembalikan sebuah iterator (dalam hal ini, keyiterator objek):
>>> d.__iter__()
<dict_keyiterator object at 0x7fb1747bee08>
Kita tidak't menggunakan metode khusus diri kita sendiri, sebaliknya, gunakan masing-masing fungsi bawaan untuk menyebutnya, iter
:
>>> key_iterator = iter(d)
>>> key_iterator
<dict_keyiterator object at 0x7fb172fa9188>
Iterator memiliki __sebelah__
metode - tetapi kita menyebutnya dengan fungsi bawaan, next
:
>>> next(key_iterator)
'x'
>>> next(key_iterator)
'y'
>>> next(key_iterator)
'z'
>>> next(key_iterator)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Ketika sebuah iterator habis, itu menimbulkan StopIteration
. Ini adalah bagaimana Python tahu untuk keluar untuk
loop, atau daftar pemahaman, atau generator ekspresi, atau lainnya berulang konteks. Setelah iterator menimbulkan StopIteration
itu akan selalu meningkatkan itu - jika anda ingin mengulanginya lagi, anda perlu yang baru.
>>> list(key_iterator)
[]
>>> new_key_iterator = iter(d)
>>> list(new_key_iterator)
['x', 'y', 'z']
Kami've melihat dicts iterasi dalam banyak konteks. Apa yang kita've terlihat adalah bahwa setiap kali kita iterate atas sebuah dict, kami mendapatkan kunci. Kembali ke aslinya contoh:
a = {'x': 1, 'y': 2, 'z': 3} untuk kunci di d:
Jika kita mengubah nama variabel, kita masih mendapatkan kunci. Let's mencobanya:
>>> for each_key in d:
... print(each_key, '=>', d[each_key])
...
x => 1
y => 2
z => 3
Jika kita ingin iterate atas nilai-nilai, kita perlu menggunakan .nilai-nilai
metode dicts, atau untuk keduanya bersama-sama, .barang-barang
:
>>> list(d.values())
[1, 2, 3]
>>> list(d.items())
[('x', 1), ('y', 2), ('z', 3)]
Dalam contoh yang diberikan, akan lebih efisien untuk iterate atas barang-barang seperti ini:
for a_key, corresponding_value in d.items():
print(a_key, corresponding_value)
Tapi untuk keperluan akademik, pertanyaan's contoh baik-baik saja.
Anda dapat memeriksa pelaksanaan CPython's dicttype
di GitHub. Ini adalah tanda tangan dari metode yang mengimplementasikan dict iterator:
_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
PyObject **pvalue, Py_hash_t *phash)
Untuk iterate atas tombol, lebih lambat tapi lebih baik menggunakan my_dict.kunci-kunci()
. Jika anda mencoba untuk melakukan sesuatu seperti ini:
for key in my_dict:
my_dict[key+"-1"] = my_dict[key]-1
itu akan membuat runtime error karena anda mengubah kunci saat program sedang berjalan. Jika anda benar-benar mengatur untuk mengurangi waktu, gunakan untuk kunci di my_dict
, tapi anda telah diperingatkan ;).