2013-06-26 4 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] 

Когда я запускаю функцию shuffle, возникает следующая ошибка: почему это так?ТипError: объект `dict_keys 'не поддерживает индексацию

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

В чем ваш вопрос? Что такое x? – Paco

+4

похоже, что вы используете python3 – oleg

+0

похоже на ошибку python3 – DataEngineer

ответ

113

Очевидно, вы передаете в d.keys() к вашей shuffle функции. Вероятно, это было написано с помощью python2.x (когда d.keys() вернул список). С python3.x, d.keys() возвращает объект dict_keys, который ведет себя намного больше как set, чем list. Таким образом, он не может быть проиндексирован.

Решение должно пройти list(d.keys()) (или просто list(d)) до shuffle.

+9

. , , Или просто «list (d)», который даст вам список ключей на обоих python2.x и python3.x без каких-либо копий :-) – mgilson

+5

Это странное решение для изменения изменений для python3. – Jason

+4

Вы можете так думать, но я определенно думаю, что это было правильное решение. Объект 'dict_keys' ведет себя намного больше, чем ключи от ключа dict. В частности, они поддерживают O (1) тестирование членства (и другие методы, подобные множеству, которые могут быть эффективно реализованы поверх этого факта). Эти вещи невозможны в списке, и если вам нужен список ключей dict, вы всегда можете просто сделать «list (your_dictionary)», чтобы получить его. – mgilson

8

Вы передаете результат somedict.keys() функции. В Python 3 dict.keys не возвращает список, но объект, похожий на набор, который представляет представление ключей словаря и (будучи установленным) не поддерживает индексацию.

Чтобы устранить проблему, воспользуйтесь list(somedict.keys()), чтобы получить ключи и работать с ними.

1

Зачем вам нужно реализовать тасование, если оно уже существует? Оставайтесь на плечах гигантов.

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

Ответ важен для общего знания, но он не касается того, что спрашивал ОП. –

+0

Вы правы. Кажется, он хочет реализовать свой рандомизатор. –

+0

psah, может быть, он на самом деле не знал, что он может использовать встроенный, но вопрос на самом деле, похоже, касается ошибки типа. Тем не менее, я надеюсь, что он переключился и использовал ваш вариант (если только он не является чем-то конкретным), чтобы следовать основным принципам DRY и кодовой экономики. –

0

новообращенный итерационный в список может стоить вместо этого вы можете использовать

next(iter(keys)) 

для первого элемента, или если вы хотите itrate все элементы используют

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

В Python 2 Dict .keys() возвращает список, тогда как в Python 3 он возвращает генератор.

Вы можете только перебирать значения, иначе вам, возможно, придется явно преобразовать их в список, то есть передать его функции списка.

+0

Просто хотел сказать, что тип возврата - это тип генератора. Надеюсь, это поможет OP! – DeWil