Ý nghĩa của thuộc tính __total__ dunder trong Python 3 là gì?


17

Trong Python 3.8 mới được phát hành, có một chú thích kiểu mới typing.TypedDict. Tài liệu của nó đề cập rằng

Thông tin loại cho nội quan có thể được truy cập thông qua Point2D.__annotations__Point2D.__total__. [....]

Mặc dù __annotations__nổi tiếng, đã được giới thiệu trong PEP 3107 , tôi không thể tìm thấy bất kỳ thông tin nào trên đó __total__. Bất cứ ai có thể giải thích ý nghĩa của nó và nếu có thể liên kết đến các nguồn có thẩm quyền?


4
Điển hình. 99% typingnội bộ không được ghi nhận và phần được ghi chép kém.
Aran-Fey

Câu trả lời:


3

Tôi đoán rằng __total__trường biểu thị cho dù các trường hợp phải hoàn thành (mặc định) hay không (tất cả các trường tùy chọn). Tôi bắt đầu tìm kiếm tại PEP 589 , nơi giới thiệu TypedDictvà mô tả toàn bộ như vậy. Nó đã sử dụng một totalđối số, sẽ hợp lý khi đổi tên kiểu dunder cho class cú pháp. Tuy nhiên, tôi đã không tìm thấy khi việc đổi tên như vậy diễn ra.

Nhìn vào MyPy, trình kiểm tra loại thực tế quan tâm đến các chú thích này, có tài liệu tương tự TypedDictvà toàn bộ , nhưng một lần nữa không có tham chiếu đến cú pháp dunder. Đi sâu vào quá trình thực hiện của nó dẫn đến nhiều nhầm lẫn hơn, vì TypedDictTypetrong type.py không có tổng trường, nhưng riêng biệt itemsrequired_keys. Totality sẽ ngụ ý điều đó items.keys()==required_keysnhưng việc thực hiện đưa ra các giả định khác nhau, chẳng hạn như can_be_falsechỉ dựa vào itemsmột mình. total=Falsenên về nguyên tắc có nghĩa required_keyslà trống rỗng.

Nguồn CPython cho _TypedDictMeta ít nhất tiết lộ rằng totalđối số và __total__dunder là một và giống nhau, mặc dù nguồn này mô tả TypedDictchính nó là "có thể được thêm sớm".


Chấp nhận điều này ngay bây giờ - nếu không phải bất cứ điều gì khác, có thể nó sẽ khiến những người khác sẵn sàng tiến lên và bác bỏ câu trả lời của bạn: D
Antti Haapala

Cá nhân tôi nghi ngờ sự cố can_be_falselà lỗi MyPy, có thể liên quan đến việc không có kế hoạch để có các trường tùy chọn ngay từ đầu.
Yann Vernier

1

TypedDictđã được chấp nhận trong Python 3.8 thông qua PEP 589 . Từ Python, nó xuất hiện __total__là một cờ boolean được đặt thành Truetheo mặc định:

tot = TypedDict.__total__
print(type(tot))
print(tot)

# <class 'bool'>
# True

Như đã đề cập trong các bài đăng khác, chi tiết về phương pháp này bị giới hạn trong các tài liệu , nhưng liên kết của @Yann Vernier với mã nguồn CPython gợi ý mạnh mẽ __total__có liên quan đến totaltừ khóa mới được giới thiệu trong Python 3.8 :

# cypthon/typing.py

class _TypedDictMeta(type):
    def __new__(cls, name, bases, ns, total=True):
        """Create new typed dict class object.
        ...
        """
        ...
        if not hasattr(tp_dict, '__total__'):
            tp_dict.__total__ = total
        ...

Làm thế nào nó hoạt động?

Tóm tắt : theo mặc định, tất cả các khóa được yêu cầu khi khởi tạo một định nghĩa TypedDict. total=Falseghi đè hạn chế này và cho phép các phím tùy chọn. Xem các cuộc biểu tình sau đây.

Được

Một cây thư mục thử nghiệm:

nhập mô tả hình ảnh ở đây

Các tập tin trong thư mục thử nghiệm:

# rgb_bad.py

from typing import TypedDict


class Color(TypedDict):
    r: int
    g: int
    b: int
    a: float


blue = Color(r=0, g=0, b=255)                     # missing "a"

# rgb_good.py

from typing import TypedDict


class Color(TypedDict, total=False):
    r: int
    g: int
    b: int
    a: float


blue = Color(r=0, g=0, b=255)                     # missing "a"

Bản giới thiệu

Nếu một khóa bị thiếu, mypy sẽ khiếu nại theo dòng lệnh:

> mypy code/rgb_bad.py
code\rgb_bad.py:11: error: Key 'a' missing for TypedDict "Color"
...

Cài đặt total=Falsecho phép các phím tùy chọn:

> mypy code/rgb_good.py
Success: no issues found in 1 source file

Xem thêm

  • Tweet của R. Hettinger tổng thể quỷ dị
  • Phần PEP về tổng số trong PEP 589
  • Điều mục trên các loại và TypedDictbằng Python 3.8 bởi Real Python
  • typing-extensionsgói để sử dụng TypedDicttrong Python 3.5, 3.6
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.