ฉันต้องการแทรกคู่คีย์ - ค่าลงใน dict ถ้าคีย์ไม่อยู่ใน dict.keys () โดยทั่วไปฉันสามารถทำได้ด้วย:
if key not in d.keys():
d[key] = value
แต่มีวิธีที่ดีกว่านี้หรือไม่? หรืออะไรคือวิธีแก้ปัญหา pythonic สำหรับปัญหานี้?
ฉันต้องการแทรกคู่คีย์ - ค่าลงใน dict ถ้าคีย์ไม่อยู่ใน dict.keys () โดยทั่วไปฉันสามารถทำได้ด้วย:
if key not in d.keys():
d[key] = value
แต่มีวิธีที่ดีกว่านี้หรือไม่? หรืออะไรคือวิธีแก้ปัญหา pythonic สำหรับปัญหานี้?
คำตอบ:
คุณไม่จำเป็นต้องโทรd.keys()
ดังนั้น
if key not in d:
d[key] = value
ก็เพียงพอแล้ว ไม่มีวิธีการอ่านที่ชัดเจนกว่านี้
คุณสามารถอัปเดตได้อีกครั้งโดยdict.get()
จะคืนค่าที่มีอยู่หากมีคีย์อยู่แล้ว:
d[key] = d.get(key, value)
แต่ฉันขอแนะนำอย่างยิ่งต่อสิ่งนี้ นี่คือการตีกอล์ฟซึ่งขัดขวางการบำรุงรักษาและความสามารถในการอ่าน
>>> d = {1: 'one'}
>>> d.setdefault(1, '1')
'one'
>>> d # d has not changed because the key already existed
{1: 'one'}
>>> d.setdefault(2, 'two')
'two'
>>> d
{1: 'one', 2: 'two'}
dict.setdefault()
ควรใช้เมื่อพยายามเข้าถึงค่าด้วย
setdefault()
อธิบายถึงสิ่งที่เกิดขึ้นอย่างชัดเจน - มันยังส่งคืนค่าที่ไม่สำคัญและ IMO ที่เล่นโวหารเล็กน้อย คุณช่วยให้คำอธิบายสั้น ๆ หรือลิงค์ไปยังที่หนึ่งได้ไหมว่าเหตุใดจึงไม่เป็นที่ต้องการ
for obj in iterable: d.setdefault(key_for_obj(obj), []).append(obj)
คุณจะใช้มันในการแสดงออกที่คาดว่าจะมีมูลค่าอยู่เช่นในวงการจัดกลุ่มต่อไปนี้: ไม่มีอะไรแปลก ๆ เกี่ยวกับการคืนค่านั่นคือจุดรวมของวิธีการนี้
if key not in d:
ทดสอบ
setdefault()
ดูเหมือนจะเข้ากับสิ่งที่คุณพูด การใช้defaultdict(list)
โค้ดจะส่งผลให้โค้ดอ่านง่ายกว่าตัวอย่างของคุณ ... ดังนั้นอาจจะไม่มีประโยชน์อะไรนอกจากจะต้องทำงานกับพจนานุกรมมาตรฐาน โดยรวมif key not in d
ชัดเจนกว่า
ตั้งแต่Python 3.9คุณสามารถใช้ตัวดำเนิน |
การผสานเพื่อรวมพจนานุกรมสองพจนานุกรมได้ คำสั่งทางด้านขวามีความสำคัญเหนือกว่า:
new_dict = old_dict | { key: val }
ตัวอย่างเช่น:
new_dict = { 'a': 1, 'b': 2 } | { 'b': 42 }
print(new_dict} # {'a': 1, 'b': 42}
หมายเหตุ: สิ่งนี้จะสร้างพจนานุกรมใหม่พร้อมค่าที่อัปเดต
ด้วยวิธีต่อไปนี้คุณสามารถแทรกค่าได้หลายค่าและยังมีค่าเริ่มต้น แต่คุณกำลังสร้างพจนานุกรมใหม่
d = {**{ key: value }, **default_values}
ฉันได้ทดสอบด้วยคำตอบที่ได้รับการโหวตมากที่สุดและโดยเฉลี่ยแล้วจะเร็วกว่าดังที่เห็นได้จากตัวอย่างต่อไปนี้
การทดสอบความเร็วเปรียบเทียบวิธีการตามลูปกับความเข้าใจตามคำบอกด้วยวิธีการแกะกล่อง
หากไม่มีการทำสำเนา ( d = default_vals.copy()
) ในกรณีแรกคำตอบที่ได้รับการโหวตมากที่สุดจะเร็วขึ้นเมื่อเราไปถึงคำสั่งที่มีขนาด10**5
และมากกว่า รอยเท้าหน่วยความจำของทั้งสองวิธีเหมือนกัน
{**default_values, **{ key: value }}
ตามคำตอบข้างต้นsetdefault ()วิธีการทำงานสำหรับฉัน
old_attr_name = mydict.setdefault(key, attr_name)
if attr_name != old_attr_name:
raise RuntimeError(f"Key '{key}' duplication: "
f"'{old_attr_name}' and '{attr_name}'.")
แม้ว่าวิธีนี้จะไม่ใช่แบบทั่วไป เหมาะกับฉันในบางกรณีนี้ วิธีแก้ปัญหาที่แน่นอนคือการตรวจสอบkey
ครั้งแรก (ตามที่ได้รับคำแนะนำไปแล้ว) แต่เมื่อsetdefault()
เราหลีกเลี่ยงการค้นหาเพิ่มเติมในพจนานุกรมนั่นคือแม้ว่าจะมีขนาดเล็ก แต่ก็ยังได้รับประสิทธิภาพ