TypeError: Das Objekt 'dict_keys' unterstützt keine Indizierung

144
def shuffle(self, x, random=None, int=int):
    """x, random=random.random -> shuffle list x in place; return None.

    Optional arg random is a 0-argument function returning a random
    float in [0.0, 1.0); by default, the standard random.random.
    """

    randbelow = self._randbelow
    for i in reversed(range(1, len(x))):
        # pick an element in x[:i+1] with which to exchange x[i]
        j = randbelow(i+1) if random is None else int(random() * (i+1))
        x[i], x[j] = x[j], x[i]

Wenn ich die shuffleFunktion ausführe, wird der folgende Fehler ausgegeben. Warum ist das so?

TypeError: 'dict_keys' object does not support indexing
gate_007
quelle
7
scheint ein Python3-Fehler zu sein
DataEngineer

Antworten:

231

Offensichtlich gehen Sie d.keys()zu Ihrer shuffleFunktion über. Wahrscheinlich wurde dies mit python2.x geschrieben (wenn d.keys()eine Liste zurückgegeben wurde). Gibt mit python3.x d.keys()ein dict_keysObjekt zurück, das sich viel mehr wie a setals wie a verhältlist . Daher kann es nicht indiziert werden.

Die Lösung besteht darin, list(d.keys())(oder einfach list(d)) zu übergeben shuffle.

mgilson
quelle
22
. . . Oder nur, list(d)was Ihnen eine Liste von Schlüsseln auf python2.x und python3.x gibt, ohne Kopien zu machen :-)
mgilson
11
Dies ist eine seltsame bahnbrechende Designentscheidung für Python3.
Jason
9
Sie mögen es denken, aber ich denke definitiv, dass es die richtige Entscheidung war. Das dict_keysObjekt verhält sich viel mehr wie nur die Schlüssel eines halben Diktats. Insbesondere unterstützen sie O (1) -Mitgliedschaftstests (und andere satzähnliche Methoden, die zusätzlich zu dieser Tatsache effizient implementiert werden können). Diese Dinge sind mit einer Liste nicht möglich, und wenn Sie eine Liste der Schlüssel des Diktats wünschen, konnten Sie dies immer einfach tun list(your_dictionary), um sie zu erhalten.
mgilson
Dies ist hilfreich für mich, um zu sehen, dass wir bei Python3 das Wörterbuch mit einer Liste versehen müssen.
DataEngineer
2
@Crt - shuffleist der Name der Funktion im Code des Originalplakats (die Funktion, die den Fehler auslöst ). Wenn ich mir den Code random.shuffle
anschaue
11

Sie übergeben das Ergebnis von somedict.keys()an die Funktion. Gibt in Python 3 dict.keyskeine Liste zurück, aber ein set-ähnliches Objekt, das eine Ansicht der Schlüssel des Wörterbuchs darstellt und (set-like) die Indizierung nicht unterstützt.

Um das Problem zu beheben, list(somedict.keys())sammeln Sie die Schlüssel und arbeiten Sie damit.

user4815162342
quelle
10

Das Konvertieren eines Iterables in eine Liste kann Kosten verursachen. Um den ersten Artikel zu erhalten, können Sie stattdessen Folgendes verwenden:

next(iter(keys))

Wenn Sie alle Elemente durchlaufen möchten, können Sie Folgendes verwenden:

items = iter(keys)
while True:
    try:
        item = next(items)
    except StopIteration as e:
        pass # finish
Sahama
quelle
1

Warum müssen Sie Shuffle implementieren, wenn es bereits vorhanden ist? Bleib auf den Schultern der Riesen.

import random

d1 = {0:'zero', 1:'one', 2:'two', 3:'three', 4:'four',
     5:'five', 6:'six', 7:'seven', 8:'eight', 9:'nine'}

keys = list(d1)
random.shuffle(keys)

d2 = {}
for key in keys: d2[key] = d1[key]

print(d1)
print(d2)
FooBar167
quelle
Die Antwort ist allgemein bekannt, bezieht sich jedoch nicht auf die Fragen des OP.
JC Rocamonde
Du hast recht. Es scheint, dass er seinen eigenen Randomizer implementieren möchte.
FooBar167
1
psah, vielleicht wusste er eigentlich nicht, dass er das eingebaute verwenden könnte, aber die frage scheint tatsächlich über einen typfehler zu sein. Trotzdem hoffe ich, dass er Ihre Option gewechselt und genutzt hat (es sei denn, es ist etwas sehr Spezifisches), um den Grundprinzipien von DRY und Code-Economy zu folgen.
JC Rocamonde
1

In Python 2 gibt dict.keys () eine Liste zurück, während in Python 3 ein Generator zurückgegeben wird.

Sie können nur über die Werte iterieren, andernfalls müssen Sie sie möglicherweise explizit in eine Liste konvertieren, dh an eine Listenfunktion übergeben.

DeWil
quelle