อะไรคือความหมายของแอตทริบิวต์ __total__ dunder ใน Python 3


17

ในออกใหม่หลาม 3.8 typing.TypedDictมีประเภทคำอธิบายประกอบใหม่ เอกสารระบุว่า

ข้อมูลประเภทสำหรับวิปัสสนาสามารถเข้าถึงได้ผ่านและPoint2D.__annotations__ Point2D.__total__[ .... ]

ในขณะที่__annotations__เป็นที่รู้จักกันดีได้รับการแนะนำในPEP 3107 , __total__ฉันไม่สามารถหาข้อมูลเกี่ยวกับ ใครสามารถอธิบายความหมายของมันและถ้าเป็นไปได้เชื่อมโยงไปยังแหล่งที่เชื่อถือได้?


4
ตามแบบฉบับ 99% ของtypinginternals ไม่ได้จัดทำเป็นเอกสารและชิ้นส่วนที่จัดทำเอกสารไม่ดี
Aran-Fey

คำตอบ:


3

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

เมื่อมองไปที่ MyPy ซึ่งเป็นตัวตรวจสอบประเภทจริงที่ใส่ใจกับคำอธิบายประกอบเหล่านี้จะมีเอกสารประกอบที่คล้ายคลึงกันTypedDictและมีจำนวนทั้งสิ้นแต่ไม่มีการอ้างอิงถึงไวยากรณ์ของ dunder อีกครั้ง ขุดลงไปในการดำเนินงานนำไปสู่ความสับสนมากขึ้นเช่นTypedDictTypeใน types.pyไม่ได้มีข้อมูลทั้งหมด แต่แยกและitems required_keysจำนวนทั้งสิ้นจะหมายความว่าitems.keys()==required_keysแต่การดำเนินการทำให้สมมติฐานที่แตกต่างกันเช่นการcan_be_falseพึ่งพาitemsคนเดียว total=Falseโดยหลักการแล้วควรrequired_keysจะว่างเปล่า

แหล่งที่มาของ CPython สำหรับ_TypedDictMetaอย่างน้อยที่สุดแสดงว่าtotalอาร์กิวเมนต์และ__total__dunder นั้นเหมือนกันแม้ว่าแหล่งข้อมูลTypedDictนั้นจะอธิบายตัวเองว่า "อาจถูกเพิ่มในไม่ช้า"


ยอมรับสิ่งนี้ในตอนนี้ - หากไม่มีสิ่งอื่นใดอาจทำให้คนอื่นเต็มใจที่จะออกมาข้างหน้าและปฏิเสธคำตอบของคุณ: D
Antti Haapala

ฉันเองสงสัยว่าcan_be_falseสิ่งนี้เป็นข้อผิดพลาดของ MyPy ซึ่งอาจเกี่ยวข้องกับการที่ไม่มีการวางแผนที่จะมีฟิลด์ตัวเลือกตั้งแต่เริ่มต้น
Yann Vernier

1

TypedDictได้รับการยอมรับในหลาม 3.8 ผ่านPEP 589 จาก Python จะ__total__มีการตั้งค่าสถานะบูลีนเป็นค่าTrueเริ่มต้น:

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

# <class 'bool'>
# True

ดังที่กล่าวไว้ในโพสต์อื่น ๆ รายละเอียดเกี่ยวกับวิธีการนี้จะถูก จำกัด ในเอกสารแต่การเชื่อมโยงของ @Yann Vernier ไปยังซอร์สโค้ด CPythonแนะนำอย่างยิ่ง__total__เกี่ยวข้องกับtotalคำหลักใหม่ที่แนะนำใน 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
        ...

มันทำงานยังไง?

เรื่องย่อ : TypedDictโดยค่าเริ่มต้นคีย์ทั้งหมดจะต้องเมื่ออินสแตนซ์ที่กำหนดไว้ total=Falseแทนที่ข้อ จำกัด นี้และอนุญาตให้ใช้คีย์ที่เป็นทางเลือก ดูการสาธิตต่อไปนี้

ป.ร. ให้ไว้

แผนผังไดเรกทอรีทดสอบ:

ป้อนคำอธิบายรูปภาพที่นี่

รหัส

ไฟล์ในไดเรกทอรีทดสอบ:

# 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"

การสาธิต

หากคีย์หายไป mypy จะบ่นที่ commandline:

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

การตั้งค่าtotal=Falseอนุญาตให้ใช้คีย์เสริม:

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

ดูสิ่งนี้ด้วย

  • ทวีตโดย R. Hettinger ทำลายล้างจำนวนทั้งสิ้น
  • ส่วน PEP เกี่ยวกับจำนวนทั้งสิ้นใน PEP 589
  • ส่วนบทความเกี่ยวกับประเภทและTypedDictใน Python 3.8 โดย Real Python
  • typing-extensionsแพ็คเกจที่ใช้TypedDictใน Python 3.5, 3.6
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.