Làm thế nào bạn sẽ kiểm tra nếu một biến là một từ điển trong Python?
Đây là một câu hỏi xuất sắc, nhưng thật không may là câu trả lời được đánh giá cao nhất dẫn đến một khuyến nghị kém, type(obj) is dict
.
(Lưu ý rằng bạn cũng không nên sử dụng dict
làm tên biến - đó là tên của đối tượng dựng sẵn.)
Nếu bạn đang viết mã sẽ được nhập và sử dụng bởi người khác, đừng cho rằng họ sẽ sử dụng trực tiếp nội dung chính - làm cho giả định đó làm cho mã của bạn không linh hoạt hơn và trong trường hợp này, hãy tạo ra các lỗi dễ dàng ẩn mà không làm lỗi chương trình .
Tôi thực sự khuyên bạn, vì mục đích chính xác, duy trì và linh hoạt cho người dùng trong tương lai, không bao giờ có các biểu thức kém linh hoạt, không phổ biến trong mã của bạn khi có các biểu thức thành ngữ, linh hoạt hơn.
is
là một bài kiểm tra cho danh tính đối tượng . Nó không hỗ trợ kế thừa, nó không hỗ trợ bất kỳ sự trừu tượng hóa nào và nó không hỗ trợ giao diện.
Vì vậy, tôi sẽ cung cấp một số tùy chọn mà làm.
Hỗ trợ thừa kế:
Đây là khuyến nghị đầu tiên tôi sẽ làm, vì nó cho phép cho người dùng để cung cấp lớp con riêng của họ dict, hoặc một OrderedDict
, defaultdict
hoặc Counter
từ các bộ sưu tập mô-đun:
if isinstance(any_object, dict):
Nhưng thậm chí còn có nhiều lựa chọn linh hoạt hơn.
Hỗ trợ trừu tượng:
from collections.abc import Mapping
if isinstance(any_object, Mapping):
Điều này cho phép người dùng mã của bạn sử dụng triển khai tùy chỉnh Bản đồ trừu tượng của riêng họ, bao gồm bất kỳ lớp con nào của dict
và vẫn có được hành vi chính xác.
Sử dụng giao diện
Bạn thường nghe lời khuyên OOP, "lập trình cho một giao diện".
Chiến lược này tận dụng tính đa hình của Python hoặc gõ vịt.
Vì vậy, chỉ cần cố gắng truy cập vào giao diện, bắt các lỗi dự kiến cụ thể ( AttributeError
trong trường hợp không có .items
và TypeError
trong trường hợp items
không thể gọi được) với một dự phòng hợp lý - và bây giờ bất kỳ lớp nào thực hiện giao diện đó sẽ cung cấp cho bạn các mục của nó (ghi chú .iteritems()
đã biến mất trong Python 3):
try:
items = any_object.items()
except (AttributeError, TypeError):
non_items_behavior(any_object)
else: # no exception raised
for item in items: ...
Có lẽ bạn có thể nghĩ rằng việc sử dụng kiểu gõ vịt như thế này đi quá xa trong việc cho phép quá nhiều thông tin sai, và có thể, tùy thuộc vào mục tiêu của bạn cho mã này.
Phần kết luận
Không sử dụng is
để kiểm tra các loại cho luồng điều khiển tiêu chuẩn. Sử dụng isinstance
, xem xét các khái niệm trừu tượng như Mapping
hoặc MutableMapping
, và xem xét tránh kiểm tra kiểu hoàn toàn, sử dụng giao diện trực tiếp.