Python2'de dict.items () ve dict.iteritems () arasındaki fark nedir?


705

dict.items()Ve arasında uygulanabilir farklar var dict.iteritems()mı?

Gönderen Python docs :

dict.items(): Sözlüğün (anahtar, değer) çiftleri listesinin bir kopyasını döndürür .

dict.iteritems(): Sözlüğün (anahtar, değer) çiftleri üzerinden bir yineleyici döndür .

Aşağıdaki kodu çalıştırırsanız, her biri aynı nesneye bir başvuru döndürüyor gibi görünüyor. Kaçırdığım ince farklar var mı?

#!/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'   

Çıktı:

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

41
Temel olarak bunların nasıl hesaplandığı konusunda bir fark var. items()öğeleri bir kerede oluşturur ve bir liste döndürür. iteritems()bir jeneratör döndürür - jeneratör her next()çağrıldığında bir defada bir öğe "oluşturan" bir nesnedir .
Joel Cornett

9
Özel durumunuzda, d[k] is vher zaman True döndürür çünkü python, -5 ile 256 arasındaki tüm tamsayılar için bir tamsayı nesnesi dizisi tutar: docs.python.org/2/c-api/int.html Bu aralıkta bir int oluşturduğunuzda, aslında sadece mevcut nesneye bir referans geri alın: >> a = 2; b = 2 >> a is b TrueAma,>> a = 1234567890; b = 1234567890 >> a is b False
t_tia

3
@the_wolf Sanırım soruda bahsettiğiniz dokümanın python sürümünü eklemek daha iyi olur.
Lorenzo Belli

2
iteritems()değişikliği iter()Python 3'te? Yukarıdaki dokümantasyon bağlantısı bu yanıtla eşleşmiyor gibi görünüyor.
Gabriel Staples

3
Tam olarak değil, @GabrielStaples. iteritems () sözlükler Python 3'ten kaldırılmıştır ve yerine başka bir şey konmamıştır. Ancak, aynı etki için, iter () işlevini kullanırsınız. örneğin iter (dict.items ()). Pep 469'a
Zim

Yanıtlar:


864

Bu bir evrimin parçası.

Başlangıçta, Python items()gerçek bir tuples listesi oluşturdu ve bunu geri verdi. Bu potansiyel olarak fazladan bellek alabilir.

Daha sonra, jeneratörler genel olarak dile tanıtıldı ve bu yöntem, adlı bir yineleyici-jeneratör yöntemi olarak yeniden uygulandı iteritems(). Orijinal geriye dönük uyumluluk için kalır.

Python 3'ün değişikliklerinden biri, items()artık yineleyicilerdir ve bir liste hiçbir zaman tam olarak oluşturulmamıştır. iteritems()Yöntem ayrıca beri gitmiş items()3 eserler gibi Python viewitems()Python 2.7.


159
Evrimde bir adımı atladığınızı unutmayın: Py3 davranışı aynı değildir iteritems(). Aslında, dict'teki değişiklikleri de yansıtan tam bir dizi protokol protokolü yapar (ve yedekli bir liste yerine dict tarafından desteklenir) - 2.7 olarak rapor edilir viewitems().
lvc

3
Bunu daha ayrıntılı olarak öğrenmek istiyorum, ancak google-fu'm beni başarısızlığa uğrattı. Birisi beni bunu daha iyi anlamama yardımcı olacak belgelere, makalelere veya kaynaklara yönlendirebilir mi? @lvc?
Güveç

10
Değişiklik açıklanan @Stew PEP 3106 ve biraz daha fazla olduğu piton 3.0 yenilikleri
Tadhg McDonald-Jensen

1
Bu eski soruyu ayrıntılandırdığı için özür dilerim ama Python 2.x'te iteritems()her zaman tercih edilenitems() doğru mu anladım ?
RubenGeert

2
@RubenGeert Çoğu zaman önemli değil. Gerçekten büyük zorlamalar için tercih edilebilir.
Keith

95

dict.items()2-tuples ( [(key, value), (key, value), ...]) listesini döndürürken 2-tuples dict.iteritems()veren bir jeneratör. Birincisi başlangıçta daha fazla yer ve zaman alır, ancak her bir öğeye erişmek hızlıdır, ikincisi başlangıçta daha az yer ve zaman alır, ancak her bir öğenin oluşturulmasında biraz daha fazla zaman alır.


9
Neden farklı olmalarını beklersiniz?
Ignacio Vazquez-Abrams

3
Dokümanlardaki "kopya" öğelerin kopyalandığı anlamına gelmez (isterseniz, kullanın copy.deepcopy). O Sözlük öğelerin bir kopyası anlamına gelir: bunu yaparsanız items = dct.items()ve sonra değiştirmek dct/ ekleme tuşları silme veya tarafından dct[k] = other_v, itemsaynı kalacaktır.
Dougal

4
Python'daki hiçbir şey, açıkça bu şekilde belgelenmedikçe, hiçbir zaman derin bir kopya değildir.
Karl Knechtel

1
@ IgnacioVazquez-Abrams - "Daha fazla yer ve zaman" ile ilgili: Ne kadar sözlükte önemli olmaya başlarlar. {1:'one', 2:'two', ... }Bir web sunucusunda yineleme yapmak ve sonuçları oluşturmak istediğim bir "büyük" sözlüğüm olduğunu varsayalım. Hangi ölçekte azından ben seçme hakkında endişe başlamalı .items()vs .iteritems()Python 2.7 için?
kullanıcı

1
@buffer: Gerçekten emin değilim. Tahminim 15-20 öğe olurdu, ama bunu test etmedim.
Ignacio Vazquez-Abrams

64

Py2.x içinde

Komutlar dict.items(), dict.keys()ve dict.values()bir dönüş kopyasını Sözlüğün ait listenin içinde (k, v)çifti, anahtarlar ve değerler. Kopyalanan liste çok büyükse bu çok fazla bellek alabilir.

Komutları dict.iteritems(), dict.iterkeys()ve dict.itervalues()bir dönüş yineleyici Sözlüğün üzerinde (k, v)çifti, anahtarlar ve değerler.

Komutlar dict.viewitems(), dict.viewkeys()ve dict.viewvalues()dönüş görünüm nesneleri Sözlüğün değişiklikleri yansıtabilir. (Yani sözlükte delbir öğe veya bir (k,v)çift eklerseniz , görüntüleme nesnesi aynı anda otomatik olarak değişebilir.)

$ 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'>

Py3.x'deyken

Py3.x, işler sadece olmadığından, daha temiz dict.items(), dict.keys()ve dict.values()geri dönme, mevcut görünüm nesneleri gibi dict.viewitems()Py2.x yaptılar içinde.

Fakat

@Lvc'in belirttiği gibi, görünüm nesnesi yineleyici ile aynı değildir , bu nedenle Py3.x'te bir yineleyici döndürmek istiyorsanız şunları kullanabilirsiniz 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'>

34

'Dict.items () ile dict.iteritems () arasında uygulanabilir farklılıklar var mı?

Bu yardımcı olabilir (Python 2.x için):

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

Bunun d.items()anahtarın tuples listesini, değer çiftlerini ve d.iteritems()sözlük-itemiterator döndürdüğünü görebilirsiniz.

Liste olarak, d.items () dilimlenebilir:

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

Ancak bir __iter__yöntemi olmazdı :

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

Bir yineleyici olarak d.iteritems () 'dir değil dilim-muktedir:

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

Ancak __iter__:

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

Böylece ürünlerin kendileri aynı - öğeleri teslim eden konteyner farklı. Biri bir liste, diğeri yineleyici (Python sürümüne bağlı olarak ...)

Dolayısıyla, dict.items () ve dict.iteritems () arasındaki uygulanabilir farklar, bir liste ile yineleyici arasındaki uygulanabilir farklarla aynıdır.


15

dict.items()tuples listesini dict.iteritems()döndürür ve tuple'ın yineleyici nesnesini sözlük olarak döndürür (key,value). Tupller aynıdır, ancak kap farklıdır.

dict.items()temel olarak tüm sözlüğü listeye kopyalar. Yürütülmesi sürelerini karşılaştırmak için aşağıdaki kodu kullanmayı deneyin dict.items()ve dict.iteritems(). Farkı göreceksin.

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

Makinemdeki çıktı:

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

Bu açıkça dictionary.iteritems()çok daha verimli olduğunu göstermektedir .


4

Eğer varsa

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

In Python 2 , dict.items()kopya her küpe ve iadeler Sözlük yani içinde dizilerini listesi [(key1,value1), (key2,value2), ...]. Bunun anlamı, sözlüğün tamamının tuples içeren yeni listeye kopyalanmasıdır

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

dict.iteritems()sözlük öğesi yineleyicisini döndürür. Döndürülen öğenin değeri de aynıdır (key1,value1), (key2,value2), ..., ancak bu bir liste değildir. Bu yalnızca sözlük öğesi yineleyici nesnesidir. Bu, daha az bellek kullanımı (% 50 daha az) anlamına gelir.

  • Değişken anlık görüntüler olarak listeler: d.items() -> list(d.items())
  • Yineleyici nesneler: d.iteritems() -> iter(d.items())

Tuples aynı. Her birinde tuples karşılaştırdınız, böylece aynı olsun.

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

Gelen Python 3 , dict.items()döner nesne adımlayıcısı. dict.iteritems () kaldırılır, böylece başka sorun kalmaz.


4

dict.iteritemsPython3.x gitti Bu yüzden iter(dict.items())aynı çıktı ve bellek tahsisi elde etmek için kullanın


1

Hem Python 2 hem de 3 ile çalışan bir sözlüğün öğe çiftlerini yinelemenin bir yolunu istiyorsanız, şöyle bir şey deneyin:

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

Şöyle kullanın:

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

0

dict.iteritems(): size bir yineleyici verir. Yineleyiciyi döngü dışındaki diğer desenlerde kullanabilirsiniz.

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')

-5

python 2'deki dict.iteritems (), python 3'teki dict.items () öğesine eşdeğerdir.


2
Bu yanlış. Fark, önceki cevaplarda zaten açıklanmıştır.
vaultah
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.