Warum müssen Sie .items () aufrufen, wenn Sie ein Wörterbuch in Python durchlaufen?

131

Warum müssen Sie aufrufen items(), um Schlüssel-Wert-Paare in einem Wörterbuch zu durchlaufen? dh.

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

Warum ist das nicht das Standardverhalten beim Durchlaufen eines Wörterbuchs?

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

Antworten:

171

Für jeden Python-Container C ist dies zu erwarten

for item in C:
    assert item in C

wird gut gehen - würden Sie es nicht erstaunlich finden, wenn ein Sinn für in(die Schleifenklausel) eine völlig andere Bedeutung hätte als der andere (die Anwesenheitsprüfung)? Ich würde sicher! Das funktioniert natürlich auch für Listen, Sets, Tupel, ...

Wenn Calso ein Wörterbuch inSchlüssel / Wert-Tupel in einer forSchleife liefert , inmüsste nach dem Prinzip des geringsten Erstaunens auch ein solches Tupel als linker Operand in der Containment-Prüfung verwendet werden.

Wie nützlich wäre das? Ziemlich nutzlos in der Tat, so dass im Grunde if (key, value) in Cein Synonym für if C.get(key) == value- das ist ein Scheck , den ich glaube , ich habe, durchgeführt, oder wollte ausführen, 100 - mal seltener als das, was if k in Ctatsächlich Mittel , die Überprüfung der Anwesenheit des Schlüssels nur und vollständig den Wert ignorieren.

Auf der anderen Seite ist es durchaus üblich, nur auf Tasten schleifen zu wollen, z.

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

den Wert auch zu haben, würde nicht besonders helfen:

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

eigentlich etwas weniger klar und weniger prägnant. (Beachten Sie, dass dies itemsdie ursprüngliche Schreibweise der "richtigen" Methoden zum Abrufen von Schlüssel / Wert-Paaren war: Leider war dies in den Tagen der Fall, als solche Accessoren ganze Listen zurückgaben. Um "nur iterieren" zu unterstützen, musste eine alternative Schreibweise eingeführt werden und iteritems es war - in Python 3, wo die Abwärtskompatibilitätsbeschränkungen mit früheren Python-Versionen stark geschwächt waren, wurde es itemswieder).

Alex Martelli
quelle
10

Meine Vermutung: Die Verwendung des vollständigen Tupels wäre für das Schleifen intuitiver, aber möglicherweise weniger für das Testen der Mitgliedschaft mit in.

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

Dieser Code würde nicht wirklich funktionieren, wenn Sie sowohl Schlüssel als auch Wert für angeben müssten in. Es fällt mir schwer, mir einen Anwendungsfall vorzustellen, in dem Sie überprüfen würden, ob sowohl der Schlüssel als auch der Wert im Wörterbuch enthalten sind. Es ist viel natürlicher, nur die Schlüssel zu testen.

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

Jetzt ist es nicht mehr erforderlich, dass der inBediener und for ... indie gleichen Elemente bearbeiten. In Bezug auf die Implementierung handelt es sich um unterschiedliche Vorgänge ( __contains__vs. __iter__). Aber diese kleine Inkonsistenz wäre etwas verwirrend und inkonsistent.

John Kugelman
quelle
Angesichts der Tatsache, dass für jede andere Art von eingebautem Iterable, an die ich denken kann, x in foonur dann , wenn iin irgendwann for i in fooden Wert von annimmt x, würde ich sagen, dass dies eine sehr große Inkonsistenz wäre.
Aaronasterling