Itereren over woordenboeken met ‘for’-lussen

Ik ben een beetje verbaasd over de volgende code:

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
    print (key, 'corresponds to', d[key])

Wat ik niet begrijp is het gedeelte key. Hoe herkent Python dat het alleen de sleutel uit het woordenboek hoeft te lezen? Is keyeen speciaal woord in Python? Of is het gewoon een variabele?


Antwoord 1, autoriteit 100%

keyis slechts een variabelenaam.

for key in d:

loopt gewoon over de sleutels in het woordenboek heen in plaats van over de sleutels en waarden. Om zowel de sleutel als de waarde te herhalen, kunt u het volgende gebruiken:

Voor Python 3.x:

for key, value in d.items():

Voor Python 2.x:

for key, value in d.iteritems():

Verander het woord keyin poopom het zelf te testen.

In Python 3.x werd iteritems()vervangen door simpelweg items(), wat een set-achtige weergave oplevert die wordt ondersteund door het dict, zoals iteritems()maar nog beter.
Dit is ook beschikbaar in 2.7 als viewitems().

De bewerking items()werkt voor zowel 2 als 3, maar in 2 wordt een lijst geretourneerd met de (key, value)-paren van het woordenboek, die niet de wijzigingen in het dictaat weerspiegelen die plaatsvinden na de items()-aanroep. Als u het 2.x-gedrag in 3.x wilt, kunt u list(d.items())aanroepen.


Antwoord 2, autoriteit 8%

Het is niet zo dat sleutel een speciaal woord is, maar dat woordenboeken het iteratorprotocol implementeren. Je zou dit in je klas kunnen doen, b.v. zie deze vraagvoor het bouwen van klasse-iterators.

In het geval van woordenboeken is het geïmplementeerd op C-niveau. De details zijn beschikbaar in PEP 234. In het bijzonder de sectie met de titel “Woordenboek Iterators”:

  • Woordenboeken implementeren een tp_iter-slot dat een efficiënt retourneert
    iterator die de sleutels van het woordenboek herhaalt. […] Dit
    betekent dat we kunnen schrijven

    for k in dict: ...
    

    wat gelijk is aan, maar veel sneller dan

    for k in dict.keys(): ...
    

    zolang de beperking op wijzigingen aan het woordenboek
    (door de lus of door een andere draad) niet worden geschonden.

  • Voeg methoden toe aan woordenboeken die verschillende soorten . retourneren
    iterators expliciet:

    for key in dict.iterkeys(): ...
    for value in dict.itervalues(): ...
    for key, value in dict.iteritems(): ...
    

    Dit betekent dat for x in dicteen afkorting is voor for x in
    dict.iterkeys()
    .

In Python 3 worden dict.iterkeys(), dict.itervalues()en dict.iteritems()niet langer ondersteund. Gebruik in plaats daarvan dict.keys(), dict.values()en dict.items().


Antwoord 3, autoriteit 4%

itereren over een dictdoorzoekt de sleutels in willekeurige volgorde, zoals je hier kunt zien:

(Dit is niet meer het geval in Python 3.6 , maar let wel dat het niet worden gegarandeerd Nog gedrag.)

>>> d = {'x': 1, 'y': 2, 'z': 3}
>>> list(d)
['y', 'x', 'z']
>>> d.keys()
['y', 'x', 'z']

Voor uw voorbeeld, is het een beter idee om gebruik te maken dict.items()

>>> d.items()
[('y', 2), ('x', 1), ('z', 3)]

Dit geeft u een lijst van tupels. Bij lus over hen als deze, waarbij elke tupel wordt uitgepakt in ken vautomatisch:

for k,v in d.items():
    print(k, 'corresponds to', v)

Gebruik ken vals variabelennamen wanneer een lus over een dictkomt vaak als het lichaam van de lus slechts een paar regels . Voor meer ingewikkelde lussen kan het een goed idee om meer beschrijvende namen te gebruiken:

for letter, number in d.items():
    print(letter, 'corresponds to', number)

Het is een goed idee te krijgen in de gewoonte van het gebruik format strings:

for letter, number in d.items():
    print('{0} corresponds to {1}'.format(letter, number))

4, Autoriteit 2%

keyis gewoon een variabele.

python2.x

d = {'x': 1, 'y': 2, 'z': 3} 
for my_var in d:
    print my_var, 'corresponds to', d[my_var]

… of beter,

d = {'x': 1, 'y': 2, 'z': 3} 
for the_key, the_value in d.iteritems():
    print the_key, 'corresponds to', the_value

Voor python3.x :

d = {'x': 1, 'y': 2, 'z': 3} 
for the_key, the_value in d.items():
    print(the_key, 'corresponds to', the_value)

5

Wanneer u door woordenboeken gewijzigt met de for .. in ..-syntax, het herhaalt altijd over de toetsen (de waarden zijn toegankelijk met dictionary[key].

Om te herinen over key-value paren, gebruik in Python 2 for k,v in s.iteritems()en in Python 3 for k,v in s.items().


6

Ik heb een gebruikscase waarin ik door het dict moet herhalen om de sleutel, waardepaar te krijgen, ook de index die aangeeft waar ik ben. Dit is hoe ik het doe:

d = {'x': 1, 'y': 2, 'z': 3} 
for i, (key, value) in enumerate(d.items()):
   print(i, key, value)

Houd er rekening mee dat de haakjes rond de sleutel, waarde belangrijk zijn, zonder deze zou u een ValueError“niet genoeg waarden om uit te pakken” krijgen.


Antwoord 7

Itereren over woordenboeken met ‘for’-lussen

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
    ...

Hoe herkent Python dat het alleen de sleutel hoeft te lezen van de
woordenboek? Is sleutel een speciaal woord in Python? Of is het gewoon een
variabel?

Het zijn niet alleen forloops. Het belangrijkste woord hier is “itereren”.

Een woordenboek is een toewijzing van sleutels aan waarden:

d = {'x': 1, 'y': 2, 'z': 3} 

Elke keer dat we het herhalen, herhalen we de sleutels. De variabelenaam keyis alleen bedoeld om te beschrijven – en het is heel geschikt voor het doel.

Dit gebeurt in een lijstbegrip:

>>> [k for k in d]
['x', 'y', 'z']

Het gebeurt wanneer we het woordenboek doorgeven aan de lijst (of een ander verzamelingstype-object):

>>> list(d)
['x', 'y', 'z']

De manier waarop Python itereert is, in een context waar het moet, het roept de __iter__methode van het object aan (in dit geval het woordenboek) die een iterator retourneert (in dit geval een keyiterator voorwerp):

>>> d.__iter__()
<dict_keyiterator object at 0x7fb1747bee08>

We zouden deze speciale methoden niet zelf moeten gebruiken, in plaats daarvan moeten we de respectievelijke ingebouwde functie gebruiken om het aan te roepen, iter:

>>> key_iterator = iter(d)
>>> key_iterator
<dict_keyiterator object at 0x7fb172fa9188>

iterators hebben een __next__-methode – maar we noemen het met de ingebouwde functie, 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

Wanneer een iterator is uitgeput, verhoogt het StopIteration. Dit is hoe Python weet om een ​​forLoop of een lijstbegrip of een generatoruitdrukking of een andere iteratieve context te verlaten. Zodra een iterator StopIterationverhoogt, wordt het altijd verhoogd – als u opnieuw wilt herhalen, hebt u een nieuwe nodig.

>>> list(key_iterator)
[]
>>> new_key_iterator = iter(d)
>>> list(new_key_iterator)
['x', 'y', 'z']

Terugkerend naar DICTS

We hebben Dictten geacht in veel contexten. Wat we hebben gezien is dat we op elk moment over een dicteren, de sleutels krijgen. Terug naar het originele voorbeeld:

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:

Als we de variabele naam wijzigen, krijgen we nog steeds de sleutels. Laten we het proberen:

>>> for each_key in d:
...     print(each_key, '=>', d[each_key])
... 
x => 1
y => 2
z => 3

Als we de waarden willen herhalen, moeten we de .valuesmethode van dicts gebruiken, of voor beide samen, .items:

>>> list(d.values())
[1, 2, 3]
>>> list(d.items())
[('x', 1), ('y', 2), ('z', 3)]

In het gegeven voorbeeld zou het efficiënter zijn om de items als volgt te herhalen:

for a_key, corresponding_value in d.items():
    print(a_key, corresponding_value)

Maar voor academische doeleinden is het voorbeeld van de vraag prima.


Antwoord 8

Je kunt de implementatie van CPython’s dicttypecontroleren op GitHub. Dit is de handtekening van de methode die de dict iterator implementeert:

_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
             PyObject **pvalue, Py_hash_t *phash)

CPython dictobject.c


Antwoord 9

Hiermee wordt de uitvoer afgedrukt in gesorteerdop waardenin oplopende volgorde.

d = {'x': 3, 'y': 1, 'z': 2}
def by_value(item):
    return item[1]
for key, value in sorted(d.items(), key=by_value):
    print(key, '->', value)

Uitvoer:

y -> 1
z -> 2
x -> 3

Antwoord 10

Om sleutels te herhalen, is het langzamer maar beter om my_dict.keys()te gebruiken. Als je zoiets als dit hebt geprobeerd:

for key in my_dict:
    my_dict[key+"-1"] = my_dict[key]-1

het zou een runtime-fout veroorzaken omdat u de sleutels wijzigt terwijl het programma draait. Als je vastbesloten bent om tijd te besparen, gebruik dan de for key in my_dict, maar je bent gewaarschuwd.


Antwoord 11

Als u op zoek bent naar een duidelijk en visueel voorbeeld:

cat  = {'name': 'Snowy', 'color': 'White' ,'age': 14}
for key , value in cat.items():
   print(key, ': ', value)

Resultaat:

name:  Snowy
color:  White
age:  14

Antwoord 12

Laten we meteen ter zake komen. Als de woordsleutel slechts een variabele is, zoals u al zei, is het belangrijkste om op te merken dat wanneer u een ‘FOR LOOP’over een woordenboek uitvoert, deze alleen door de ‘sleutels’ loopt en negeert de ‘waarden’.

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
    print (key, 'corresponds to', d[key])

probeer liever dit:

d = {'x': 1, 'y': 2, 'z': 3} 
for i in d:
    print (i, 'corresponds to', d[i])

maar als je een functie gebruikt zoals:

d = {'x': 1, 'y': 2, 'z': 3}
print(d.keys())

in het bovenstaande geval is ‘keys’gewoon geen variabele, het is een functie.

Other episodes