Perché devi chiamare .items () quando si scorre su un dizionario in Python?


131

Perché è necessario chiamare items()per scorrere le coppie chiave-valore in un dizionario? vale a dire.

dic = {'one': '1', 'two': '2'}
for k, v in dic.items():
    print(k, v)

Perché non è questo il comportamento predefinito di iterare su un dizionario

for k, v in dic:
    print(k, v)

Risposte:


171

Per ogni contenitore C di Python, l'aspettativa è quella

for item in C:
    assert item in C

passerà bene - non ti sembrerebbe sorprendente se un senso diin (la clausola del ciclo) avesse un significato completamente diverso dall'altro (il controllo di presenza)? Lo farei sicuramente! Funziona naturalmente in questo modo per elenchi, set, tuple, ...

Quindi, quando Cè un dizionario, se si indovessero produrre tuple chiave / valore in un forciclo, allora, per principio di minimo stupore, si indovrebbe prendere una tupla come l'operando di sinistra nel controllo di contenimento.

Quanto sarebbe utile? Abbastanza inutile anzi, in pratica facendo if (key, value) in Cun sinonimo di if C.get(key) == value- che è un assegno Credo di aver eseguito, o voluto eseguire, 100 volte più raramente di quello che if k in Cin realtà significa , verificare la presenza della chiave unica e ignorando completamente il valore.

D'altra parte, voler girare in loop solo sui tasti è abbastanza comune, ad esempio:

for k in thedict:
    thedict[k] += 1

avere anche questo valore non aiuterebbe in particolare:

for k, v in thedict.items():
    thedict[k] = v + 1

in realtà un po 'meno chiaro e meno conciso. (Si noti che itemsera l'ortografia originale dei metodi "corretti" da utilizzare per ottenere coppie chiave / valore: sfortunatamente era nei giorni in cui tali accessori restituivano intere liste, quindi per supportare "solo iterando" si doveva introdurre un'ortografia alternativa ed iteritems è stato - in Python 3, dove i vincoli di compatibilità con le versioni precedenti di Python erano molto indeboliti, è diventato di itemsnuovo).


10

La mia ipotesi: l' uso della tupla completa sarebbe più intuitivo per il looping, ma forse meno per il test per l'utilizzo dell'appartenenza in.

if key in counts:
    counts[key] += 1
else:
    counts[key] = 1

Quel codice non funzionerebbe davvero se dovessi specificare sia la chiave che il valore per in. Sto facendo fatica a immaginare un caso d'uso in cui verifichi se nel dizionario sono presenti sia la chiave AND sia il valore. È molto più naturale testare solo i tasti.

# When would you ever write a condition like this?
if (key, value) in dict:

Ora non è necessario che l' inoperatore for ... inoperi sugli stessi articoli. Dal punto di vista dell'implementazione sono diverse operazioni ( __contains__vs. __iter__). Ma quella piccola incoerenza sarebbe alquanto confusa e, beh, incoerente.


Dato che per ogni altro tipo di built-in iterabile a cui posso pensare, x in foosolo sei in for i in fooassume il valore di xad un certo punto, direi che sarebbe un'enorme incoerenza.
aaronasterling,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.