พจนานุกรมภาษาไพ ธ อน


386

เป็นไปได้ไหมที่จะสร้างความเข้าใจในพจนานุกรมใน Python (สำหรับปุ่ม)?

คุณสามารถใช้สิ่งนี้:

l = []
for n in range(1, 11):
    l.append(n)

เราสามารถย่อให้สั้นลงไปสู่รายการความเข้าใจ: l = [n for n in range(1, 11)].

อย่างไรก็ตามพูดว่าฉันต้องการตั้งค่าคีย์ของพจนานุกรมเป็นค่าเดียวกัน ที่ฉันสามารถทำได้:

d = {}
for n in range(1, 11):
     d[n] = True # same value for each

ฉันเคยลองแล้ว:

d = {}
d[i for i in range(1, 11)] = True

แต่ผมได้รับในSyntaxErrorfor

นอกจากนี้ (ฉันไม่ต้องการส่วนนี้ แต่เพียงแค่สงสัย) คุณสามารถตั้งค่าคีย์ของพจนานุกรมให้มีค่าแตกต่างกันดังนี้:

d = {}
for n in range(1, 11):
    d[n] = n

เป็นไปได้ด้วยความเข้าใจในพจนานุกรมหรือไม่

d = {}
d[i for i in range(1, 11)] = [x for x in range(1, 11)]

นอกจากนี้ยังยกบนSyntaxErrorfor


3
สำหรับข้อมูลผู้อ่านในอนาคต: อาร์เรย์ NumPy ช่วยให้คุณกำหนดองค์ประกอบหลายรายการเป็นค่าเดียวหรือรายการค่าวิธีที่คุณพยายามทำ แม้ว่าคุณจะไม่มีเหตุผลที่จะใช้ NumPy แต่ก็อาจไม่คุ้มค่ากับคุณสมบัตินี้
David Z

คำตอบ:


520

มีความเข้าใจในพจนานุกรมใน Python 2.7ขึ้นไป แต่มันไม่ได้ทำงานอย่างที่คุณต้องการ เช่นเดียวกับความเข้าใจในรายการพวกเขาสร้างพจนานุกรมใหม่ คุณไม่สามารถใช้มันเพื่อเพิ่มคีย์ให้กับพจนานุกรมที่มีอยู่ได้ นอกจากนี้คุณต้องระบุคีย์และค่าแม้ว่าคุณจะสามารถระบุค่าตัวอย่างได้หากต้องการ

>>> d = {n: n**2 for n in range(5)}
>>> print d
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

หากคุณต้องการตั้งค่าทั้งหมดเป็น True:

>>> d = {n: True for n in range(5)}
>>> print d
{0: True, 1: True, 2: True, 3: True, 4: True}

สิ่งที่คุณดูเหมือนจะขอเป็นวิธีการตั้งค่าหลายปุ่มพร้อมกันในพจนานุกรมที่มีอยู่ ไม่มีทางลัดโดยตรงสำหรับสิ่งนั้น คุณสามารถวนซ้ำตามที่คุณแสดงหรือคุณสามารถใช้ความเข้าใจในพจนานุกรมเพื่อสร้าง dict ใหม่ด้วยค่าใหม่จากนั้นทำการoldDict.update(newDict)ผสานค่าใหม่เข้ากับ dict เก่า


15
FWIW dict.updateสามารถยอมรับคู่คีย์ - ค่าที่ซ้ำได้เช่นเดียวกับตัวdictสร้าง
mgilson

6
dict.fromkeys()โปรดทราบว่าถ้าคุณสามารถสร้างพจนานุกรมที่มีค่าเหมือนกันทั้งหมดใช้ ดังนั้นการตั้งค่าทั้งหมดที่จะใช้True dict.fromkeys(range(5), True)ระวังค่าจะไม่ถูกคัดลอกดังนั้นคุณอาจต้องการหลีกเลี่ยงปัญหานี้เมื่อคุณมีค่าที่ไม่แน่นอน มันจะถูกแชร์ระหว่างคีย์ทั้งหมด
Martijn Pieters

2
หมายเหตุ: ปุ่มต่างๆสามารถเป็นผลลัพธ์ของวิธีการได้เช่นกัน: { n*2 : n for n in range(3) } => {0: 0, 2: 1, 4: 2}. ทั้งสองสามารถทำได้ในนิพจน์เดียวกัน: { n*2 : n*3 for n in range(3) } => { 0: 0, 2: 3, 4: 6 }.
Zaaier

151

คุณสามารถใช้dict.fromkeysวิธีการเรียน ...

>>> dict.fromkeys(range(5), True)
{0: True, 1: True, 2: True, 3: True, 4: True}

นี่เป็นวิธีที่เร็วที่สุดในการสร้างพจนานุกรมโดยที่ปุ่มทั้งหมดจะจับคู่กับค่าเดียวกัน

แต่จะไม่ใช้วิธีนี้กับวัตถุที่ไม่แน่นอน :

d = dict.fromkeys(range(5), [])
# {0: [], 1: [], 2: [], 3: [], 4: []}
d[1].append(2)
# {0: [2], 1: [2], 2: [2], 3: [2], 4: [2]} !!!

หากคุณไม่จำเป็นต้องเริ่มต้นคีย์ทั้งหมดจริง ๆa defaultdictอาจมีประโยชน์เช่นกัน:

from collections import defaultdict
d = defaultdict(True)

ในการตอบคำถามในส่วนที่สองความเข้าใจในประโยคเป็นเพียงสิ่งที่คุณต้องการ:

{k: k for k in range(10)}

คุณอาจไม่ควรทำสิ่งนี้ แต่คุณสามารถสร้างคลาสย่อยdictที่ทำงานคล้ายกับdefaultdictถ้าคุณแทนที่__missing__:

>>> class KeyDict(dict):
...    def __missing__(self, key):
...       #self[key] = key  # Maybe add this also?
...       return key
... 
>>> d = KeyDict()
>>> d[1]
1
>>> d[2]
2
>>> d[3]
3
>>> print(d)
{}

โปรดทราบว่าในกรณีของd = defaultdict(lambda: True)แลมบ์ดานั้นไม่จำเป็นเนื่องจาก True คือ (หรือไม่ควร) เปลี่ยนแปลงได้
rhbvkleef


22

ฉันชอบความคิดเห็นของ @mgilson เนื่องจากถ้าคุณมีค่า iterables สองอันอันหนึ่งที่สอดคล้องกับคีย์และค่าอื่น ๆ คุณสามารถทำสิ่งต่อไปนี้ได้

keys = ['a', 'b', 'c']
values = [1, 2, 3]
d = dict(zip(keys, values))

ให้

d = {'a': 1, 'b': 2, 'c': 3}


4
ใช้ Dict Comprehension:{i:j for i in keys for j in values}
LoMaPh

11

ใช้ dict () ในรายการของ tuples วิธีนี้จะช่วยให้คุณมีค่าตามอำเภอใจในแต่ละรายการตราบใดที่มีความยาวเท่ากัน

i_s = range(1, 11)
x_s = range(1, 11)
# x_s = range(11, 1, -1) # Also works
d = dict([(i_s[index], x_s[index], ) for index in range(len(i_s))])

12
นี่คือสิ่งเดียวกับd = dict(zip(i_s,x_s))
mgilson

10

ลองพิจารณาตัวอย่างการนับจำนวนคำที่ปรากฏในรายการโดยใช้ความเข้าใจในพจนานุกรม

my_list = ['hello', 'hi', 'hello', 'today', 'morning', 'again', 'hello']
my_dict = {k:my_list.count(k) for k in my_list}
print(my_dict)

และผลที่ได้คือ

{'again': 1, 'hi': 1, 'hello': 3, 'today': 1, 'morning': 1}

นี่เป็นเรื่องที่น่าสนใจแม้ว่าจะไม่ได้ผลที่สุดเท่าที่คุณจะนับจำนวนปุ่มเช่น 'สวัสดี' หลายครั้ง
FuriousGeorge

7

วัตถุประสงค์หลักของรายการความเข้าใจคือการสร้างรายการใหม่โดยใช้รายการอื่นโดยไม่เปลี่ยนแปลงหรือทำลายรายการดั้งเดิม

แทนที่จะเขียน

    l = []
    for n in range(1, 11):
        l.append(n)

หรือ

    l = [n for n in range(1, 11)]

คุณควรเขียนเท่านั้น

    l = range(1, 11)

ในบล็อกรหัสสองอันดับแรกที่คุณกำลังสร้างรายการใหม่วนซ้ำและส่งคืนแต่ละองค์ประกอบ เป็นเพียงวิธีการสร้างสำเนารายการที่มีราคาแพง

ในการรับพจนานุกรมใหม่ที่มีปุ่มทั้งหมดถูกตั้งค่าเป็นค่าเดียวกันโดยอ้างอิงจาก dict อื่นให้ทำดังนี้

    old_dict = {'a': 1, 'c': 3, 'b': 2}
    new_dict = { key:'your value here' for key in old_dict.keys()}

คุณได้รับ SyntaxError เพราะเมื่อคุณเขียน

    d = {}
    d[i for i in range(1, 11)] = True

คุณกำลังพูดว่า: "ตั้งค่าคีย์ของฉัน 'i for i ในช่วง (1, 11)' เป็น True" และ "i for i ในช่วง (1, 11)" ไม่ใช่คีย์ที่ถูกต้องมันเป็นเพียงข้อผิดพลาดทางไวยากรณ์ หากแสดงรายการที่สนับสนุนเป็นคีย์คุณจะทำสิ่งที่ต้องการ

    d[[i for i in range(1, 11)]] = True

และไม่

    d[i for i in range(1, 11)] = True

แต่รายการจะไม่แฮชดังนั้นคุณจึงไม่สามารถใช้เป็นคีย์ dict ได้


-3

คุณไม่สามารถแฮชรายการแบบนั้นได้ ลองใช้มันแทนการใช้สิ่งอันดับ

d[tuple([i for i in range(1,11)])] = True
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.