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 key
een speciaal woord in Python? Of is het gewoon een variabele?
Antwoord 1, autoriteit 100%
key
is 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 key
in poop
om 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 schrijvenfor 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 dict
een afkorting is voorfor 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 dict
doorzoekt 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 k
en v
automatisch:
for k,v in d.items():
print(k, 'corresponds to', v)
Gebruik k
en v
als variabelennamen wanneer een lus over een dict
komt 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%
key
is 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 for
loops. 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 key
is 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 for
Loop of een lijstbegrip of een generatoruitdrukking of een andere iteratieve context te verlaten. Zodra een iterator StopIteration
verhoogt, 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 .values
methode 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 dicttype
controleren 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)
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.