Trả về Không nếu khóa Từ điển không khả dụng


489

Tôi cần một cách để có được một giá trị từ điển nếu khóa của nó tồn tại, hoặc đơn giản là trả về None, nếu nó không có.

Tuy nhiên, Python đưa ra một KeyErrorngoại lệ nếu bạn tìm kiếm một khóa không tồn tại. Tôi biết rằng tôi có thể kiểm tra chìa khóa, nhưng tôi đang tìm kiếm một cái gì đó rõ ràng hơn. Có cách nào để trở lại Nonenếu khóa không tồn tại?


74
Chỉ cần sử dụng .get(key)thay vì[key]
Gabe

12
Một dict đưa ra một ngoại lệ KeyError. Nó không "trả lại key_error".
Ber

3
Truy cập khóa và bắt ngoại lệ là hoàn toàn ổn trong Python. Nó thậm chí là một mẫu thiết kế nổi tiếng và được sử dụng. Nếu bạn trả về Không thay vào đó, sẽ không thể lưu trữ Không có giá trị, có thể có liên quan trong một số trường hợp.
Ber

1
Đôi khi bạn muốn xử lý các mục "Không" trong từ điển và các mục bị thiếu giống nhau, trong trường hợp đó, câu trả lời được chấp nhận dường như làm tốt công việc.
cib

@Ber Tôi đã chỉnh sửa câu hỏi để làm rõ. Bạn có thể đã làm như vậy là tốt.
törzsmókus

Câu trả lời:


813

Bạn có thể dùng dict.get()

value = d.get(key)

Mà sẽ trở lại Nonenếu key is not in d. Bạn cũng có thể cung cấp một giá trị mặc định khác sẽ được trả về thay vì None:

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

47
Lưu ý rằng biến thể thứ hai với dự phòng mặc định vẫn sẽ quay trở lại Nonenếu khóa được ánh xạ rõ ràng Nonetrong dict. Nếu đó không phải là những gì bạn muốn, bạn có thể sử dụng một cái gì đó như d.get(key) or "empty".
cib

15
@cib: Điểm tốt, nhưng giải pháp có một vấn đề tương tự - nếu khóa được ánh xạ tới bất kỳ giá trị "falsy" (như [], "", False, 0.0hoặc thực sựNone ), sau đó giải pháp của bạn sẽ luôn luôn trở lại 0. Nếu bạn mong đợi Nones là giá trị, bạn sẽ phải if key in d:kiểm tra rõ ràng.
Tim Pietzcker

1
@cib cổ vũ cho điều đó, tôi không thể tìm ra những gì tôi đã làm sai ở đây.
wobbily_col

@TimPietzcker - bạn có thể vui lòng giải thích câu trả lời của bạn không? d.get (khóa) hoặc "trống" trong trường hợp khóa được ánh xạ tới bất kỳ giá trị 'giả mạo' nào là "trống" nếu tôi không nhầm.
MiloMinderbinder

@MiloMinderbinder: "empty"được trả về nếu keykhông phải là khóa hợp lệ d. Nó không có gì để làm với giá trị keyđược ánh xạ tới.
Tim Pietzcker

63

Tự hỏi không còn nữa. Nó được tích hợp vào ngôn ngữ.

    >>> giúp đỡ (chính tả)

    Trợ giúp về dict lớp trong nội dung mô-đun:

    lớp dict (đối tượng)
     | dict () -> từ điển trống mới
     | dict (ánh xạ) -> từ điển mới được khởi tạo từ một đối tượng ánh xạ
     | cặp (khóa, giá trị)
    ...
     |  
     | được(...)
     | D.get (k [, d]) -> D [k] nếu k ở D, khác d. d mặc định là Không có.
     |  
    ...

22

Sử dụng dict.get

Trả về giá trị cho khóa nếu khóa nằm trong từ điển, mặc định khác. Nếu mặc định không được cung cấp, nó mặc định là Không có, do đó phương thức này không bao giờ tăng KeyError.


19

Bạn nên sử dụng get()phương thức từ dictlớp

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

Điều này sẽ dẫn đến r == None. Nếu khóa không được tìm thấy trong từ điển, hàm get sẽ trả về đối số thứ hai.


19
Bạn không cần phải vượt qua Nonemột cách rõ ràng. Nó là mặc định.
Bjorn Pollex

18

Nếu bạn muốn một giải pháp minh bạch hơn, bạn có thể phân lớp dictđể có hành vi này:

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: Như tôi đã đề cập trong một bình luận cho một câu trả lời khác, vấn đề với defaultdictnó là nó sẽ phát triển mỗi khi một yếu tố chưa được yêu cầu. Điều này không phải lúc nào cũng mong muốn.
Bjorn Pollex

@ BjornPollex Đây là một trong những thanh lịch, Bất kỳ manh mối về cách mở rộng này để hỗ trợ bất kỳ chiều sâu? Ý tôi là làm foo['bar']['test']['sss']cho trở về Nonethay vì ngoại lệ, Sau một chiều sâu, nó bắt đầu cho TypeErrorthay vìKeyError
nehem

@itsneo. Bạn có thể xây dựng toàn bộ cấu trúc củaNoneDicts . Điều này sẽ giúp trong trường hợp điều KeyErrorđó sẽ xảy ra trong đối tượng trong cùng. Mặt khác, vấn đề là, một khi bạn trả lại một Noneđối tượng, bạn không thể đăng ký nó nữa. Một hack xấu xí sẽ là trả lại một đối tượng khác mà thử nghiệm None. Hãy coi chừng rằng điều này có thể dẫn đến các lỗi khủng khiếp.
magu_

@ BjornPollex Có ổn không khi đổi return dict.get(self, key)sang return super().get(key)? Sau đó, nếu tôi quyết định sử dụng OrderedDict thay vì dict, tôi không phải lo lắng về việc thay đổi nhiều dòng mã.
Gỗ

@Wood Vâng, điều đó thực sự sẽ đẹp hơn nhiều!
Bjorn Pollex

12

Tôi thường sử dụng defaultdict cho các tình huống như thế này. Bạn cung cấp một phương thức xuất xưởng không có đối số và tạo giá trị khi thấy khóa mới. Nó hữu ích hơn khi bạn muốn trả về một cái gì đó như một danh sách trống trên các khóa mới ( xem các ví dụ ).

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

19
Vấn đề với defaultdictnó là nó sẽ tiếp tục phát triển mỗi khi một yếu tố không tồn tại được yêu cầu.
Bjorn Pollex

8

Bạn có thể sử dụng phương thức dictcủa đối tượng get(), như những người khác đã đề xuất. Ngoài ra, tùy thuộc vào chính xác những gì bạn đang làm, bạn có thể sử dụng một try/exceptbộ như thế này:

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

Đây được coi là một cách tiếp cận rất "Pythonic" để xử lý vụ việc.


7

Một giải pháp một dòng sẽ là:

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

Điều này hữu ích khi cố gắng thêm giá trị từ điển vào danh sách mới và muốn cung cấp mặc định:

ví dụ.

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

5

Như những người khác đã nói ở trên, bạn có thể sử dụng get ().

Nhưng để kiểm tra chìa khóa, bạn cũng có thể làm:

d = {}
if 'keyname' in d:

    # d['keyname'] exists
    pass

else:

    # d['keyname'] does not exist
    pass

Bây giờ tôi thấy rằng bạn đã biết làm thế nào để làm điều này. Tôi sẽ xóa bài viết của mình, nhưng tôi sẽ để nó để tham khảo cho người khác.
Marek P

4
Cách tiếp cận này thường đòi hỏi chìa khóa phải được tra cứu hai lần khi nó ở đó, đó có lẽ là lý do của getphương pháp.
martineau

0

Tôi đã bị bất ngờ bởi những gì có thể xảy ra trong python2 vs python3. Tôi sẽ trả lời nó dựa trên những gì tôi đã làm cho python3. Mục tiêu của tôi rất đơn giản: kiểm tra xem phản hồi json ở định dạng từ điển có bị lỗi hay không. Từ điển của tôi được gọi là "mã thông báo" và khóa của tôi mà tôi đang tìm kiếm là "lỗi". Tôi đang tìm khóa "lỗi" và nếu nó không ở đó, đặt nó thành giá trị là Không, thì việc kiểm tra là giá trị là Không, nếu vậy hãy tiếp tục với mã của tôi. Một câu lệnh khác sẽ xử lý nếu tôi có "lỗi" khóa.

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

-2

Nếu bạn có thể làm điều đó với False, thì, cũng có chức năng tích hợp hasattr :

e=dict()
hasattr(e, 'message'):
>>> False
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.