TypeError: 'dict_keys'オブジェクトはインデックス作成をサポートしていません


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]

shuffle関数を実行すると、次のエラーが発生します。なぜですか?

TypeError: 'dict_keys' object does not support indexing

7
python3エラーのようです
DataEngineer

回答:


231

明らかd.keys()に、shuffle関数に渡しています。おそらくこれはpython2.xで書かれたものです(d.keys()リストが返されたとき)。python3.xで、d.keys()返すdict_keysより多くのように振る舞うオブジェクトset以外をlist。そのため、インデックスを作成することはできません。

解決策はに渡すlist(d.keys())(または単にlist(d))ことshuffleです。


22
。。。またはlist(d)、コピーを作成せずにpython2.xとpython3.xの両方のキーのリストを表示するだけです:-)
mgilson

11
これはpython3の奇妙な重大な変更の設計決定です。
Jason

9
そう思うかもしれませんが、間違いなく正しい判断だったと思います。dict_keysオブジェクトは、多くの辞書のちょうどキーの半分のように振る舞います。具体的には、O(1)メンバーシップテスト(およびその事実の上に効率的に実装できる他のセットのようなメソッド)をサポートします。これらのことはリストでは不可能であり、辞書のキーのリストが必要な場合は、いつでも簡単list(your_dictionary)に取得できます。
mgilson 2017年

これは、python3が辞書をリストでラップする必要があることを確認するのに役立ちます。
DataEngineer 2017年

2
@Crt- shuffle元の投稿者のコード内の関数の名前(エラーをスローしている関数)。コードを見ると、random.shuffle標準ライブラリの実装からコピー/貼り付けされていたと思います:-)
mgilson '17年

11

の結果をsomedict.keys()関数に渡しています。Python 3ではdict.keysリストは返されませんが、辞書のキーのビューを表すセットのようなオブジェクトであり、(セットのように)インデックス付けをサポートしていません。

問題を解決するには、を使用list(somedict.keys())してキーを収集し、それを使用します。


10

イテラブルをリストに変換するにはコストがかかる場合があります。代わりに、最初のアイテムを取得するには、次を使用できます。

next(iter(keys))

または、すべてのアイテムを繰り返し処理したい場合は、次を使用できます。

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

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)

回答は一般的な知識に関連していますが、OPが求めていた内容には対応していません。
JCロカモンデ2017

あなたが正しい。彼は自分のランダマイザーを実装したいようです。
FooBar167 2017

1
ええ、たぶん彼はビルトインを使用できることを実際に知らなかったかもしれませんが、問題は実際にはタイプエラーに関するようです。それでも、彼が切り替えて、(非常に具体的なものでない限り)基本的なDRYとコード経済の原則に従うためにあなたのオプションを使用したことを願っています。
JCロカモンデ2017

1

Python 2ではdict.keys()がリストを返しますが、Python 3ではジェネレータを返します。

あなたはそれの値を反復することしかできません、さもなければ明示的にそれをリストに変換する必要があるかもしれません、すなわちそれをリスト関数に渡します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.