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

คำตอบ:


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วัตถุทำงานมากขึ้นเช่นเดียวกับปุ่มครึ่งหนึ่งของ Dict โดยเฉพาะพวกเขาสนับสนุนการทดสอบสมาชิก O (1) (และวิธีการที่เหมือนชุดอื่น ๆ ที่สามารถนำไปปฏิบัติได้อย่างมีประสิทธิภาพเหนือความจริงนั้น) สิ่งเหล่านี้เป็นไปไม่ได้ในรายการและถ้าคุณต้องการรายการคีย์ของ dict คุณก็สามารถทำได้list(your_dictionary)เพื่อให้ได้มา
mgilson

สิ่งนี้มีประโยชน์สำหรับฉันที่จะเห็นว่า python3 ต้องการให้เราห่อพจนานุกรมด้วยรายการ
DataEngineer

2
@Crt - shuffleเป็นชื่อของฟังก์ชั่นในรหัสของโปสเตอร์ต้นฉบับ (ฟังก์ชั่นที่จะโยนข้อผิดพลาด) ดูรหัสฉันคิดว่ามันถูกคัดลอก / วางจากrandom.shuffleการใช้งานในไลบรารีมาตรฐาน :-)
mgilson

11

คุณกำลังส่งผ่านผลลัพธ์ของsomedict.keys()ฟังก์ชัน ใน Python 3 dict.keysจะไม่ส่งคืนรายการ แต่วัตถุ set-like ที่แสดงมุมมองของคีย์ของพจนานุกรมและ (เป็น set-like) ไม่รองรับการทำดัชนี

เพื่อแก้ไขปัญหาใช้list(somedict.keys())เพื่อรวบรวมกุญแจและทำงานกับมัน


10

แปลง iterable เป็นรายการอาจมีค่าใช้จ่าย เพื่อรับไอเท็มแรกคุณสามารถใช้:

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 Rocamonde

คุณถูก. ดูเหมือนว่าเขาต้องการใช้เครื่องมือสุ่มของเขาเอง
FooBar167

1
psah บางทีเขาอาจไม่รู้จริง ๆ ว่าเขาสามารถใช้ built-in ได้ แต่คำถามจริง ๆ แล้วดูเหมือนว่าจะเกี่ยวกับข้อผิดพลาดประเภท ถึงกระนั้นฉันหวังว่าเขาจะเปลี่ยนและใช้ตัวเลือกของคุณ (เว้นแต่เป็นสิ่งที่เฉพาะเจาะจงมาก) เพื่อปฏิบัติตามหลักการพื้นฐานของ DRY และรหัสเศรษฐกิจ
JC Rocamonde

1

ใน Python 2 dict.keys () คืนค่ารายการในขณะที่ใน Python 3 จะส่งคืนตัวสร้าง

คุณสามารถทำซ้ำมันเป็นค่าอื่น ๆ ที่คุณอาจต้องแปลงเป็นรายการอย่างชัดเจนเช่นส่งผ่านไปยังฟังก์ชันรายการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.