Apa perbedaan antara dict.items () dan dict.iteritems () di Python2?

705

Apakah ada perbedaan yang berlaku antara dict.items()dan dict.iteritems()?

Dari dokumen Python :

dict.items(): Kembalikan salinan daftar pasangan (kunci, nilai) kamus.

dict.iteritems(): Kembalikan iterator melalui pasangan (kunci, nilai) kamus.

Jika saya menjalankan kode di bawah ini, masing-masing tampaknya mengembalikan referensi ke objek yang sama. Apakah ada perbedaan halus yang saya lewatkan?

#!/usr/bin/python

d={1:'one',2:'two',3:'three'}
print 'd.items():'
for k,v in d.items():
   if d[k] is v: print '\tthey are the same object' 
   else: print '\tthey are different'

print 'd.iteritems():'   
for k,v in d.iteritems():
   if d[k] is v: print '\tthey are the same object' 
   else: print '\tthey are different'   

Keluaran:

d.items():
    they are the same object
    they are the same object
    they are the same object
d.iteritems():
    they are the same object
    they are the same object
    they are the same object
serigala
sumber
41
Pada dasarnya ada perbedaan dalam bagaimana mereka dihitung. items()membuat item sekaligus dan mengembalikan daftar. iteritems()mengembalikan generator - generator adalah objek yang "menciptakan" satu item pada suatu waktu setiap kali next()dipanggil.
Joel Cornett
9
Dalam kasus khusus Anda, d[k] is vakan selalu mengembalikan True karena python menyimpan array objek integer untuk semua integer antara -5 dan 256: docs.python.org/2/c-api/int.html Ketika Anda membuat sebuah int dalam kisaran itu, Anda sebenarnya hanya mendapatkan kembali referensi ke objek yang ada: >> a = 2; b = 2 >> a is b TrueTapi,>> a = 1234567890; b = 1234567890 >> a is b False
t_tia
3
@ the_wolf Saya pikir akan lebih baik untuk menambahkan versi python dari dokumen yang Anda maksud dalam pertanyaan.
Lorenzo Belli
2
Apakah ada iteritems()perubahan iter()pada Python 3? Tautan dokumentasi di atas sepertinya tidak cocok dengan jawaban ini.
Gabriel Staples
3
Tidak juga, @GabrielStaples. iteritems () dihapus dari kamus Python 3, dan tidak memiliki pengganti. Namun, untuk efek yang sama, Anda menggunakannya iter (). mis iter (dict.items ()). Lihat pep 469: python.org/dev/peps/pep-0469
Zim

Jawaban:

864

Itu bagian dari evolusi.

Awalnya, Python items()membuat daftar tupel dan mengembalikannya. Itu berpotensi mengambil banyak memori ekstra.

Kemudian, generator diperkenalkan ke bahasa secara umum, dan metode itu diterapkan kembali sebagai metode iterator-generator yang dinamai iteritems(). Dokumen asli tetap untuk kompatibilitas ke belakang.

Salah satu perubahan Python 3 adalah items()sekarang mengembalikan iterator, dan daftar tidak pernah sepenuhnya dibangun. The iteritems()Metode juga hilang, karena items()di Python 3 karya seperti viewitems()di Python 2.7.

Keith
sumber
159
Perhatikan bahwa Anda telah melewatkan langkah dalam evolusi: perilaku Py3 tidak sama dengan iteritems(). Ini benar-benar membuat objek protokol urutan penuh yang juga mencerminkan perubahan pada dikt (dan didukung oleh dikt itu sendiri, bukan daftar yang berlebihan) - itu telah di-backport ke 2,7 sebagai viewitems().
Lvc
3
Saya ingin belajar tentang ini secara lebih rinci, tetapi google-fu saya gagal. Bisakah seseorang mengarahkan saya ke dokumentasi, artikel atau sumber yang akan membantu saya lebih memahami hal ini? @lvc?
Rebus
10
@Stew perubahan dijelaskan dalam PEP 3106 dan ada sedikit lebih banyak dalam apa yang baru dalam python 3.0
Tadhg McDonald-Jensen
1
Maaf untuk menguraikan pertanyaan kuno ini tetapi apakah saya mengerti benar bahwa iteritems()selalu lebih disukai daripadaitems() di Python 2.x
RubenGeert
2
@ RubenGeert Sebagian besar waktu, tidak masalah. Untuk dict yang benar-benar besar mungkin lebih disukai.
Keith
95

dict.items()mengembalikan daftar 2-tupel ( [(key, value), (key, value), ...]), sedangkan dict.iteritems()generator yang menghasilkan 2-tupel. Yang pertama membutuhkan lebih banyak ruang dan waktu pada awalnya, tetapi mengakses setiap elemen dengan cepat, sedangkan yang kedua membutuhkan lebih sedikit ruang dan waktu pada awalnya, tetapi sedikit lebih banyak waktu dalam menghasilkan setiap elemen.

Ignacio Vazquez-Abrams
sumber
9
Mengapa Anda berharap mereka berbeda?
Ignacio Vazquez-Abrams
3
"Salin" dalam dokumen tidak berarti bahwa elemen disalin (jika Anda menginginkannya, gunakan copy.deepcopy). Ini berarti bahwa ini adalah salinan dari item kamus: jika Anda lakukan items = dct.items()dan kemudian memodifikasi dctdengan menambahkan / menghapus kunci atau dct[k] = other_v, itemsakan tetap sama.
Dougal
4
Tidak ada dalam Python yang merupakan salinan yang dalam kecuali didokumentasikan secara eksplisit.
Karl Knechtel
1
@ IgnacioVazquez-Abrams - Mengenai "lebih banyak ruang dan waktu": Pada ukuran kamus apa mereka mulai penting. Katakanlah saya memiliki kamus "besar" {1:'one', 2:'two', ... }yang ingin saya ulangi di server web dan render hasilnya. Pada skala apa saya harus mulai khawatir tentang memilih .items()vs .iteritems()untuk Python 2.7?
pengguna
1
@ buffer: Tidak begitu yakin. Perkiraan saya adalah 15-20 item, tapi saya belum mengujinya.
Ignacio Vazquez-Abrams
64

Di Py2.x

Perintah dict.items(), dict.keys()dan dict.values()mengembalikan salinan dari kamus ini daftar dari (k, v)pasangan, kunci dan nilai-nilai. Ini bisa memakan banyak memori jika daftar yang disalin sangat besar.

Perintah dict.iteritems(), dict.iterkeys()dan dict.itervalues()kembalikan iterator pada (k, v)pasangan kamus , kunci dan nilai.

Perintah dict.viewitems(), dict.viewkeys()dan dict.viewvalues()mengembalikan objek tampilan , yang dapat mencerminkan perubahan kamus. (Yaitu jika Anda delitem atau menambahkan (k,v)pasangan dalam kamus, objek tampilan dapat secara otomatis berubah pada saat yang sama.)

$ python2.7

>>> d = {'one':1, 'two':2}
>>> type(d.items())
<type 'list'>
>>> type(d.keys())
<type 'list'>
>>> 
>>> 
>>> type(d.iteritems())
<type 'dictionary-itemiterator'>
>>> type(d.iterkeys())
<type 'dictionary-keyiterator'>
>>> 
>>> 
>>> type(d.viewitems())
<type 'dict_items'>
>>> type(d.viewkeys())
<type 'dict_keys'>

Sementara di Py3.x

Di Py3.x, segalanya lebih bersih, karena hanya ada dict.items(), dict.keys()dan dict.values()tersedia, yang mengembalikan objek tampilan seperti dict.viewitems()pada Py2.x.

Tapi

Seperti yang dicatat @lvc, objek tampilan tidak sama dengan iterator , jadi jika Anda ingin mengembalikan iterator di Py3.x, Anda bisa menggunakan iter(dictview):

$ python3.3

>>> d = {'one':'1', 'two':'2'}
>>> type(d.items())
<class 'dict_items'>
>>>
>>> type(d.keys())
<class 'dict_keys'>
>>>
>>>
>>> ii = iter(d.items())
>>> type(ii)
<class 'dict_itemiterator'>
>>>
>>> ik = iter(d.keys())
>>> type(ik)
<class 'dict_keyiterator'>
YaOzI
sumber
34

Anda bertanya: 'Apakah ada perbedaan yang berlaku antara dict.items () dan dict.iteritems ()'

Ini dapat membantu (untuk Python 2.x):

>>> d={1:'one',2:'two',3:'three'}
>>> type(d.items())
<type 'list'>
>>> type(d.iteritems())
<type 'dictionary-itemiterator'>

Anda dapat melihat bahwa d.items()mengembalikan daftar tupel kunci, pasangan nilai dand.iteritems() mengembalikan kamus-itemiterator.

Sebagai daftar, d.items () dapat diiris:

>>> l1=d.items()[0]
>>> l1
(1, 'one')   # an unordered value!

Tetapi tidak akan memiliki __iter__metode:

>>> next(d.items())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list object is not an iterator

Sebagai iterator, d.iteritems () tidak dapat diiris:

>>> i1=d.iteritems()[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'dictionary-itemiterator' object is not subscriptable

Tetapi memang memiliki __iter__:

>>> next(d.iteritems())
(1, 'one')               # an unordered value!

Jadi barangnya sendiri sama - wadah yang mengantarkan barang berbeda. Satu adalah daftar, yang lain merupakan iterator (tergantung pada versi Python ...)

Jadi perbedaan yang berlaku antara dict.items () dan dict.iteritems () sama dengan perbedaan yang berlaku antara daftar dan iterator.

dawg
sumber
15

dict.items()mengembalikan daftar tupel, dan dict.iteritems()mengembalikan objek itupator tupel dalam kamus sebagai (key,value). Tupelnya sama, tetapi wadahnya berbeda.

dict.items()pada dasarnya menyalin semua kamus ke dalam daftar. Coba gunakan kode berikut untuk membandingkan waktu eksekusi dict.items()dan dict.iteritems(). Anda akan melihat perbedaannya.

import timeit

d = {i:i*2 for i in xrange(10000000)}  
start = timeit.default_timer() #more memory intensive
for key,value in d.items():
    tmp = key + value #do something like print
t1 = timeit.default_timer() - start

start = timeit.default_timer()
for key,value in d.iteritems(): #less memory intensive
    tmp = key + value
t2 = timeit.default_timer() - start

Output di mesin saya:

Time with d.items(): 9.04773592949
Time with d.iteritems(): 2.17707300186

Ini jelas menunjukkan bahwa dictionary.iteritems()jauh lebih efisien.

Prabhu
sumber
4

Jika Anda memiliki

dict = {key1:value1, key2:value2, key3:value3,...}

Dalam Python 2 , dict.items()menyalin setiap tupel dan mengembalikan daftar tupel dalam kamus yaitu [(key1,value1), (key2,value2), ...]. Implikasinya adalah bahwa seluruh kamus disalin ke daftar baru yang berisi tupel

dict = {i: i * 2 for i in xrange(10000000)}  
# Slow and memory hungry.
for key, value in dict.items():
    print(key,":",value)

dict.iteritems()mengembalikan iterator item kamus. Nilai item yang dikembalikan juga sama yaitu (key1,value1), (key2,value2), ..., tetapi ini bukan daftar. Ini hanya objek item iterator kamus. Itu berarti lebih sedikit penggunaan memori (50% lebih sedikit).

  • Daftar sebagai snapshot yang bisa diubah: d.items() -> list(d.items())
  • Objek Iterator: d.iteritems() -> iter(d.items())

Tupelnya sama. Anda membandingkan tupel di masing-masing sehingga Anda mendapatkan yang sama.

dict = {i: i * 2 for i in xrange(10000000)}  
# More memory efficient.
for key, value in dict.iteritems():
    print(key,":",value)

Dalam Python 3 , dict.items()mengembalikan objek iterator. dict.iteritems () dihapus sehingga tidak ada masalah lagi.

Hary Bakta
sumber
4

dict.iteritemshilang di Python3.x Jadi gunakan iter(dict.items())untuk mendapatkan output dan alokasi memori yang sama

Tessaracter
sumber
1

Jika Anda ingin cara untuk mengulangi pasangan item kamus yang berfungsi dengan Python 2 dan 3, coba sesuatu seperti ini:

DICT_ITER_ITEMS = (lambda d: d.iteritems()) if hasattr(dict, 'iteritems') else (lambda d: iter(d.items()))

Gunakan seperti ini:

for key, value in DICT_ITER_ITEMS(myDict):
    # Do something with 'key' and/or 'value'.
R. Navega
sumber
0

dict.iteritems(): memberi Anda sebuah iterator. Anda dapat menggunakan iterator dalam pola lain di luar loop.

student = {"name": "Daniel", "student_id": 2222}

for key,value in student.items():
    print(key,value)

('student_id', 2222)
('name', 'Daniel')

for key,value in student.iteritems():
    print(key,value)

('student_id', 2222)
('name', 'Daniel')

studentIterator = student.iteritems()

print(studentIterator.next())
('student_id', 2222)

print(studentIterator.next())
('name', 'Daniel')
Ethplumber
sumber
-5

dict.iteritems () di python 2 sama dengan dict.items () di python 3.

pengguna128364
sumber
2
Ini salah. Perbedaannya sudah dijelaskan dalam jawaban sebelumnya.
vaultah