ส่งคืนไม่มีถ้าไม่มีคีย์พจนานุกรม


489

ฉันต้องการวิธีในการรับค่าพจนานุกรมหากมีกุญแจอยู่หรือเพียงคืนค่าNoneถ้าไม่มี

อย่างไรก็ตาม Python จะสร้างKeyErrorข้อยกเว้นหากคุณค้นหาคีย์ที่ไม่มีอยู่ ฉันรู้ว่าฉันสามารถตรวจสอบกุญแจได้ แต่ฉันกำลังมองหาบางอย่างที่ชัดเจนยิ่งขึ้น มีวิธีการส่งคืนหรือไม่Noneหากคีย์ไม่มีอยู่?


74
เพียงใช้.get(key)แทน[key]
Gabe

12
dict เพิ่มข้อยกเว้น KeyError ไม่ใช่ "return key_error"
เบอร์

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

1
บางครั้งคุณต้องการที่จะปฏิบัติต่อรายการ "ไม่มี" ในพจนานุกรมและรายการที่ขาดหายไปเหมือนกันในกรณีนั้นคำตอบที่ยอมรับได้ดูเหมือนว่าจะทำงานได้ดี
cib

@Ber ฉันได้แก้ไขคำถามเพื่อชี้แจง คุณสามารถทำได้เช่นกัน
törzsmókus

คำตอบ:


813

คุณสามารถใช้ได้ dict.get()

value = d.get(key)

ซึ่งจะกลับมาถ้าNone key is not in dคุณยังสามารถระบุค่าเริ่มต้นอื่นที่จะส่งคืนแทนNone:

value = d.get(key, "empty")

47
โปรดทราบว่าตัวแปรที่สองที่มีทางเลือกเริ่มต้นจะยังคงกลับมาNoneหากคีย์ถูกแมปอย่างชัดเจนNoneใน dict d.get(key) or "empty"หากนั่นไม่ใช่สิ่งที่คุณต้องการคุณสามารถใช้สิ่งที่ต้องการ
cib

15
@cib: จุดดี แต่วิธีการแก้ปัญหามีปัญหาที่คล้ายกัน - ถ้าคีย์ถูกแมปไปใด ๆ "falsy" ค่า (เช่น[], "", False, 0.0หรือแน่นอนNone) 0แล้ววิธีการแก้ปัญหาของคุณจะกลับมาเสมอ หากคุณคาดหวังว่าNoneเป็นค่าคุณจะต้องทำการif key in d:ตรวจสอบอย่างชัดเจน
ทิม Pietzcker

1
@cib ไชโยฉันไม่สามารถทำสิ่งที่ฉันทำผิดที่นี่
wobbily_col

@TimPietzcker - คุณช่วยอธิบายคำตอบของคุณได้ไหม? d.get (คีย์) หรือ "ว่าง" ในกรณีที่คีย์ถูกแมปกับค่า 'เท็จ' ใด ๆ คือ "ว่างเปล่า" ถ้าฉันไม่เข้าใจผิด
MiloMinderbinder

@MiloMinderbinder: "empty"ถูกส่งกลับถ้าไม่ได้เป็นคีย์ที่ถูกต้องในkey dมันไม่มีส่วนเกี่ยวข้องกับค่าที่keyแม็พไว้
ทิม Pietzcker

63

ไม่ต้องสงสัยอีกแล้ว มันสร้างเป็นภาษา

    >>> ความช่วยเหลือ (dict)

    ช่วยในคลาส dict ในโมดูล builtins:

    คลาส dict (วัตถุ)
     | dict () -> พจนานุกรมว่างใหม่
     | dict (การแมป) -> พจนานุกรมใหม่ที่เริ่มต้นจากวัตถุการแมป
     | คู่ (คีย์, ค่า)
    ...
     |  
     | ได้รับ ( ... )
     | D.get (k [, d]) -> D [k] ถ้า k ใน D เป็นอย่างอื่น d d ค่าเริ่มต้นเป็นไม่มี
     |  
    ...

22

ใช้ dict.get

ส่งคืนค่าสำหรับคีย์หากคีย์อยู่ในพจนานุกรมมิฉะนั้นจะเป็นค่าเริ่มต้น หากไม่ได้กำหนดค่าเริ่มต้นจะมีค่าเริ่มต้นเป็นไม่มีดังนั้นวิธีนี้จะไม่เพิ่ม KeyError


19

คุณควรใช้get()วิธีการจากdictชั้นเรียน

d = {}
r = d.get('missing_key', None)

r == Noneซึ่งจะส่งผล หากไม่พบกุญแจในพจนานุกรมฟังก์ชัน get จะส่งกลับอาร์กิวเมนต์ที่สอง


19
คุณไม่ต้องผ่านNoneอย่างชัดเจน มันเป็นค่าเริ่มต้น
Björn Pollex

18

หากคุณต้องการโซลูชันที่โปร่งใสมากขึ้นคุณสามารถคลาสย่อยdictเพื่อรับพฤติกรรมนี้:

class NoneDict(dict):
    def __getitem__(self, key):
        return dict.get(self, key)

>>> foo = NoneDict([(1,"asdf"), (2,"qwerty")])
>>> foo[1]
'asdf'
>>> foo[2]
'qwerty'
>>> foo[3] is None
True

2
@marineau: ตามที่ฉันได้กล่าวถึงในความคิดเห็นต่อคำตอบอื่นปัญหาของdefaultdictมันคือมันจะเพิ่มขึ้นทุกครั้งที่องค์ประกอบที่ยังไม่ได้มีการร้องขอ สิ่งนี้ไม่เป็นที่ต้องการเสมอไป
Björn Pollex

@ BjörnPollexนี่คือสิ่งที่สวยงามและมีเงื่อนงำเกี่ยวกับวิธีการขยายนี้เพื่อรองรับความลึกใด ๆ ? ฉันหมายถึงการfoo['bar']['test']['sss']กลับไปNoneแทนที่จะเป็นข้อยกเว้นหลังจากหนึ่งความลึกมันเริ่มให้TypeErrorแทนKeyError
nehem

@itsneo NoneDictsคุณสามารถสร้างโครงสร้างทั้งหมดของ สิ่งนี้จะช่วยในกรณีที่KeyErrorเกิดขึ้นในวัตถุชั้นในสุด มิฉะนั้นปัญหาคือเมื่อคุณคืนค่าNoneวัตถุคุณจะไม่สามารถสมัครสมาชิกได้อีกต่อไป แฮ็คที่น่าเกลียดคนหนึ่งจะกลับวัตถุอื่นที่ทดสอบเช่นNoneนั้น ระวังอย่างไรก็ตามสิ่งนี้อาจนำไปสู่ข้อผิดพลาดที่น่ากลัว
magu_

@ BjörnPollexเปลี่ยนreturn dict.get(self, key)เป็นreturn super().get(key)ใช่ไหม? ถ้าฉันตัดสินใจใช้ OrderedDict แทน dict ฉันไม่ต้องกังวลกับการเปลี่ยนรหัสหลายบรรทัด
ไม้

@ ไม้ใช่ว่าจริง ๆ แล้วจะดีกว่ามาก!
Björn Pollex

12

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

from collections import defaultdict
d = defaultdict(lambda: None)
print d['new_key']  # prints 'None'

19
ปัญหาdefaultdictคือมันจะเติบโตขึ้นทุกครั้งที่มีการร้องขอองค์ประกอบที่ไม่มีอยู่
Björn Pollex

8

คุณสามารถใช้วิธีการdictของวัตถุget()ตามที่คนอื่นแนะนำไว้แล้ว อีกทางหนึ่งขึ้นอยู่กับสิ่งที่คุณทำคุณอาจใช้try/exceptชุดดังนี้:

try:
   <to do something with d[key]>
except KeyError:
   <deal with it not being there>

ซึ่งถือว่าเป็นวิธี "Pythonic" มากในการจัดการคดี


7

โซลูชันบรรทัดเดียวคือ:

item['key'] if 'key' in item else None

สิ่งนี้มีประโยชน์เมื่อพยายามเพิ่มค่าพจนานุกรมลงในรายการใหม่และต้องการระบุค่าเริ่มต้น:

เช่น.

row = [item['key'] if 'key' in item else 'default_value']

5

ดังที่คนอื่น ๆ พูดไว้ข้างต้นคุณสามารถใช้รับ ()

แต่หากต้องการตรวจสอบคีย์คุณสามารถทำได้:

d = {}
if 'keyname' in d:

    # d['keyname'] exists
    pass

else:

    # d['keyname'] does not exist
    pass

ตอนนี้ฉันเห็นแล้วว่าคุณรู้วิธีการทำสิ่งนี้อยู่แล้ว ฉันจะลบโพสต์ของฉัน แต่ฉันจะทิ้งไว้เพื่ออ้างอิงสำหรับผู้อื่น
Marek P

4
วิธีการนี้มักจะต้องใช้กุญแจที่จะค้นหาสองครั้งเมื่อมันมีซึ่งอาจเป็นเหตุผลสำหรับgetวิธีการ
martineau

0

ฉันถูกผงะโดยสิ่งที่เป็นไปได้ใน python2 กับ python3 ฉันจะตอบมันตามสิ่งที่ฉันทำลงไปสำหรับ python3 วัตถุประสงค์ของฉันง่ายมาก: ตรวจสอบว่าการตอบสนอง json ในรูปแบบพจนานุกรมมีข้อผิดพลาดหรือไม่ พจนานุกรมของฉันเรียกว่า "โทเค็น" และกุญแจที่ฉันต้องการคือ "ข้อผิดพลาด" ฉันกำลังมองหา "ข้อผิดพลาด" ที่สำคัญและหากไม่มีการตั้งค่าเป็นไม่มีค่าการตรวจสอบคือค่าเป็นไม่มีหากดำเนินการต่อด้วยรหัสของฉัน คำสั่งอื่นจะจัดการถ้าฉันมี "ข้อผิดพลาด" ที่สำคัญ

if ((token.get('error', None)) is None):
    do something

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