ภาพรวม
คำถามได้รับการแก้ไขแล้ว อย่างไรก็ตามคำตอบนี้ได้เพิ่มตัวอย่างที่ใช้ได้จริงเพื่อช่วยในการทำความเข้าใจพื้นฐานเกี่ยวกับแว่นตาข้อมูล
คลาสข้อมูล python คืออะไรและควรใช้เมื่อใด
- เครื่องกำเนิดรหัส : สร้างรหัสสำเร็จรูป; คุณสามารถเลือกใช้วิธีพิเศษในคลาสปกติหรือให้คลาสดาต้าใช้โดยอัตโนมัติ
- ภาชนะบรรจุข้อมูล : โครงสร้างที่ข้อมูลถือ (เช่น tuples และ dicts) มักจะมีประเข้าถึงแอตทริบิวต์เช่นการเรียน
namedtuple
และอื่น ๆ
"mutable namedtuples โดยมีค่าเริ่มต้น [s]"
นี่คือความหมายของวลีหลัง:
- เปลี่ยนแปลงไม่ได้ : โดยค่าเริ่มต้นแอตทริบิวต์ dataclass สามารถกำหนดใหม่ได้ คุณสามารถเลือกที่จะทำให้ไม่เปลี่ยนรูปได้ (ดูตัวอย่างด้านล่าง)
- namedtuple : คุณมีจุดการเข้าถึงแอตทริบิวต์เช่น a
namedtuple
หรือคลาสปกติ
- ค่าเริ่มต้น : คุณสามารถกำหนดค่าเริ่มต้นให้กับแอตทริบิวต์
เมื่อเทียบกับคลาสทั่วไปคุณจะประหยัดค่าใช้จ่ายในการพิมพ์โค้ดสำเร็จรูปเป็นหลัก
คุณสมบัติ
นี่คือภาพรวมของคุณลักษณะ dataclass (TL; DR หรือไม่ดูตารางสรุปในหัวข้อถัดไป)
สิ่งที่คุณได้รับ
นี่คือคุณสมบัติที่คุณจะได้รับโดยค่าเริ่มต้นจาก dataclasses
คุณสมบัติ + การเป็นตัวแทน + การเปรียบเทียบ
import dataclasses
@dataclasses.dataclass
#@dataclasses.dataclass() # alternative
class Color:
r : int = 0
g : int = 0
b : int = 0
ค่าเริ่มต้นเหล่านี้มีให้โดยการตั้งค่าคำสำคัญต่อไปนี้เป็นTrue
:
@dataclasses.dataclass(init=True, repr=True, eq=True)
สิ่งที่คุณสามารถเปิดได้
True
คุณสมบัติเพิ่มเติมที่มีอยู่หากคำหลักที่เหมาะสมมีการกำหนดให้
ใบสั่ง
@dataclasses.dataclass(order=True)
class Color:
r : int = 0
g : int = 0
b : int = 0
ขณะนี้มีการใช้วิธีการสั่งซื้อ (ตัวดำเนินการมากเกินไป :) < > <= >=
เช่นเดียวfunctools.total_ordering
กับการทดสอบความเท่าเทียมกันที่แข็งแกร่งขึ้น
แฮส, เปลี่ยนแปลงได้
@dataclasses.dataclass(unsafe_hash=True) # override base `__hash__`
class Color:
...
แม้ว่าวัตถุอาจเปลี่ยนแปลงได้ (อาจไม่ต้องการ) แต่ก็มีการใช้แฮช
แฮสได้ไม่เปลี่ยนรูป
@dataclasses.dataclass(frozen=True) # `eq=True` (default) to be immutable
class Color:
...
ขณะนี้มีการใช้แฮชและไม่อนุญาตให้เปลี่ยนอ็อบเจ็กต์หรือกำหนดให้กับแอ็ตทริบิวต์
โดยรวมแล้ววัตถุนั้นสามารถแฮชได้ถ้าอย่างใดอย่างหนึ่งunsafe_hash=True
หรือfrozen=True
.
ดูตารางลอจิกการแฮชต้นฉบับพร้อมรายละเอียดเพิ่มเติม
สิ่งที่คุณไม่ได้รับ
ในการรับคุณสมบัติดังต่อไปนี้ต้องใช้วิธีพิเศษด้วยตนเอง:
แกะกล่อง
@dataclasses.dataclass
class Color:
r : int = 0
g : int = 0
b : int = 0
def __iter__(self):
yield from dataclasses.astuple(self)
การเพิ่มประสิทธิภาพ
@dataclasses.dataclass
class SlottedColor:
__slots__ = ["r", "b", "g"]
r : int
g : int
b : int
ตอนนี้ขนาดวัตถุลดลง:
>>> imp sys
>>> sys.getsizeof(Color)
1056
>>> sys.getsizeof(SlottedColor)
888
ในบางสถานการณ์__slots__
ยังช่วยเพิ่มความเร็วในการสร้างอินสแตนซ์และการเข้าถึงแอตทริบิวต์ นอกจากนี้ช่องไม่อนุญาตให้มีการกำหนดค่าเริ่มต้น มิฉะนั้น a ValueError
จะถูกยกขึ้น
ดูเพิ่มเติมเกี่ยวกับสล็อตในบล็อกโพสต์นี้
ตารางสรุป
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
| Feature | Keyword | Example | Implement in a Class |
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
| Attributes | init | Color().r -> 0 | __init__ |
| Representation | repr | Color() -> Color(r=0, g=0, b=0) | __repr__ |
| Comparision* | eq | Color() == Color(0, 0, 0) -> True | __eq__ |
| | | | |
| Order | order | sorted([Color(0, 50, 0), Color()]) -> ... | __lt__, __le__, __gt__, __ge__ |
| Hashable | unsafe_hash/frozen | {Color(), {Color()}} -> {Color(r=0, g=0, b=0)} | __hash__ |
| Immutable | frozen + eq | Color().r = 10 -> TypeError | __setattr__, __delattr__ |
| | | | |
| Unpacking+ | - | r, g, b = Color() | __iter__ |
| Optimization+ | - | sys.getsizeof(SlottedColor) -> 888 | __slots__ |
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
+วิธีการเหล่านี้ไม่ได้สร้างขึ้นโดยอัตโนมัติและต้องใช้งานด้วยตนเองใน dataclass
* __ne__
ไม่จำเป็นจึงไม่ได้ดำเนินการ
คุณลักษณะเพิ่มเติม
โพสต์เริ่มต้น
@dataclasses.dataclass
class RGBA:
r : int = 0
g : int = 0
b : int = 0
a : float = 1.0
def __post_init__(self):
self.a : int = int(self.a * 255)
RGBA(127, 0, 255, 0.5)
# RGBA(r=127, g=0, b=255, a=127)
มรดก
@dataclasses.dataclass
class RGBA(Color):
a : int = 0
การแปลง
แปลง dataclass เป็น tuple หรือ dict แบบวนซ้ำ :
>>> dataclasses.astuple(Color(128, 0, 255))
(128, 0, 255)
>>> dataclasses.asdict(Color(128, 0, 255))
{r: 128, g: 0, b: 255}
ข้อ จำกัด
อ้างอิง
- คำพูดของR.Hettingerเกี่ยวกับDataclasses: ตัวสร้างรหัสเพื่อยุติการสร้างโค้ดทั้งหมด
- คำพูดของ T. Hunner ในเรื่องEasier Classes: Python Classes Without All the Cruft
- เอกสารของ Python เกี่ยวกับรายละเอียดการแฮช
- คำแนะนำของ Real Python เกี่ยวกับThe Ultimate Guide to Data Classes ใน Python 3.7
- บล็อกโพสต์ของ A. Shaw เกี่ยวกับการแนะนำคลาสข้อมูล Python 3.7 โดยย่อ
- ที่เก็บ githubของE.Smithบนdataclasses
namedtuple
s ไม่เปลี่ยนรูปและไม่สามารถมีค่าเริ่มต้นสำหรับแอตทริบิวต์ในขณะที่คลาสข้อมูลไม่แน่นอนและสามารถมีได้