2013-06-26 12 views
67
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] 

Quando si esegue la funzione shuffle, viene generato il seguente errore, perché?TypeError: l'oggetto 'dict_keys' non supporta l'indicizzazione

TypeError: 'dict_keys' object does not support indexing 
+0

Qual è la tua domanda? Cos'è x? – Paco

+4

sembra che tu stia usando python3 – oleg

+0

sembra essere un errore python3 – DataEngineer

risposta

113

Chiaramente si sta passando in d.keys() alla funzione shuffle. Probabilmente questo è stato scritto con python2.x (quando d.keys() ha restituito un elenco). Con python3.x, d.keys() restituisce un oggetto dict_keys che si comporta molto più come un set di uno list. In quanto tale, non può essere indicizzato.

La soluzione è passare list(d.keys()) (o semplicemente list(d)) a shuffle.

+9

. . . O semplicemente 'lista (d)' che ti darà una lista di chiavi sia su python2.x che su python3.x senza fare nessuna copia :-) – mgilson

+5

Questa è una strana decisione sul cambiamento di rotta per python3. – Jason

+4

Si potrebbe pensare così, ma io sicuramente penso che sia stata la decisione corretta. L'oggetto 'dict_keys' si comporta molto più come la metà dei tasti di un ditt. In particolare, supportano il test di appartenenza O (1) (e altri metodi set-like che possono essere implementati in modo efficiente in aggiunta a questo fatto). Queste cose non sono possibili con una lista e se vuoi una lista delle chiavi del dict, sei sempre stato in grado di fare semplicemente 'list (your_dictionary)' per ottenerlo. – mgilson

8

Si sta passando il risultato di somedict.keys() alla funzione. In Python 3, dict.keys non restituisce un elenco, ma un oggetto set-like che rappresenta una vista delle chiavi del dizionario e (essendo impostato come) non supporta l'indicizzazione.

Per risolvere il problema, utilizzare list(somedict.keys()) per raccogliere le chiavi e lavorare con quello.

1

Perché è necessario implementare shuffle quando già esiste? Rimani sulle spalle dei giganti.

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) 
+0

La risposta è rilevante in termini di conoscenza generale, ma non si riferisce a ciò che l'OP chiedeva. –

+0

Hai ragione. Sembra che voglia implementare il suo randomizzatore. –

+0

psah, forse in realtà non sapeva che poteva usare il built-in, ma la domanda in realtà sembra riguardare un errore di tipo. Comunque, spero che abbia cambiato e usato la tua opzione (a meno che non sia qualcosa di molto specifico) per seguire i principi base di DRY e codice-economia. –

0

convertito iterativo per elenco può costare invece di esso è possibile utilizzare

next(iter(keys)) 

per il primo oggetto o se si desidera itrate tutti gli elementi utilizzare

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

In Python 2 dict .keys() restituisce una lista, mentre in Python 3 restituisce un generatore.

Si potrebbe solo iterare sui suoi valori altrimenti potrebbe essere necessario convertirlo in modo esplicito in un elenco, ad esempio passarlo a una funzione di elenco.

+0

Volevo solo dire che il tipo di ritorno è quello di un generatore. Spero che aiuti l'OP! – DeWil

Problemi correlati