genel bakış
Soru ele alındı. Bununla birlikte, bu cevap, veri sınıflarının temel anlayışına yardımcı olacak bazı pratik örnekler ekler.
Python veri sınıfları tam olarak nedir ve bunları ne zaman kullanmak en iyisidir?
- kod üreteçleri : standart kod üretir; normal bir sınıfta özel yöntemler uygulamayı seçebilir veya bir veri sınıfının bunları otomatik olarak uygulamasını sağlayabilirsiniz.
- veri taşıyıcıları: genellikle sınıflar
namedtuple
ve diğerleri gibi noktalı öznitelik erişimine sahip verileri tutan yapılar (örn. tuple ve dicts) .
"varsayılan [ler] ile değişken adlandırılmış çiftler"
İkinci ifade şu anlama gelir:
- değiştirilebilir : varsayılan olarak, veri sınıfı nitelikleri yeniden atanabilir. İsteğe bağlı olarak onları değişmez hale getirebilirsiniz (aşağıdaki Örneklere bakın).
- namedtuple : a
namedtuple
veya normal bir sınıf gibi noktalı, öznitelik erişiminiz var .
- varsayılan : niteliklere varsayılan değerler atayabilirsiniz.
Yaygın sınıflarla karşılaştırıldığında, öncelikle standart kod yazmaktan tasarruf edersiniz.
Özellikleri
Bu, veri sınıfı özelliklerine genel bir bakıştır (TL; DR? Bir sonraki bölümdeki Özet Tablosuna bakın).
Ne olsun
Veri sınıflarından varsayılan olarak aldığınız özellikler şunlardır.
Nitelikler + Temsil + Karşılaştırma
import dataclasses
@dataclasses.dataclass
#@dataclasses.dataclass() # alternative
class Color:
r : int = 0
g : int = 0
b : int = 0
Bu varsayılanlar, aşağıdaki anahtar kelimelerin otomatik olarak ayarlanmasıyla sağlanır True
:
@dataclasses.dataclass(init=True, repr=True, eq=True)
Ne açabilirsin
Uygun anahtar sözcükler olarak ayarlanmışsa ek özellikler kullanılabilir True
.
Sipariş
@dataclasses.dataclass(order=True)
class Color:
r : int = 0
g : int = 0
b : int = 0
Sıralama yöntemleri artık daha güçlü eşitlik testlerine < > <= >=
benzer şekilde uygulanmaktadır (aşırı yükleme operatörleri functools.total_ordering
:).
Hashable, Değişebilir
@dataclasses.dataclass(unsafe_hash=True) # override base `__hash__`
class Color:
...
Nesne potansiyel olarak değişebilir (muhtemelen istenmeyen) olsa da, bir hash uygulanır.
Hashable, Immutable
@dataclasses.dataclass(frozen=True) # `eq=True` (default) to be immutable
class Color:
...
Artık bir karma uygulanmıştır ve nesneyi değiştirmeye veya özniteliklere atamaya izin verilmez.
Genel olarak, nesne ya unsafe_hash=True
da ise hashable'dır frozen=True
.
Daha fazla ayrıntı içeren orijinal karma mantık tablosuna da bakın.
Ne anlamıyorsun
Aşağıdaki özellikleri elde etmek için özel yöntemler manuel olarak uygulanmalıdır:
Ambalajın açılması
@dataclasses.dataclass
class Color:
r : int = 0
g : int = 0
b : int = 0
def __iter__(self):
yield from dataclasses.astuple(self)
Optimizasyon
@dataclasses.dataclass
class SlottedColor:
__slots__ = ["r", "b", "g"]
r : int
g : int
b : int
Nesne boyutu artık küçültülmüştür:
>>> imp sys
>>> sys.getsizeof(Color)
1056
>>> sys.getsizeof(SlottedColor)
888
Bazı durumlarda, __slots__
örnek oluşturma ve özniteliklere erişme hızını da artırır. Ayrıca, yuvalar varsayılan atamalara izin vermez; aksi takdirde, a ValueError
yükseltilir.
Bu blog gönderisindeki slotlar hakkında daha fazlasını görün .
Özet Tablosu
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
| 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__ |
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
+ Bu yöntemler otomatik olarak oluşturulmaz ve bir veri sınıfında manuel uygulama gerektirir.
* __ne__
gerekli değildir ve bu nedenle uygulanmaz .
Ek özellikler
Sonrası başlatma
@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)
miras
@dataclasses.dataclass
class RGBA(Color):
a : int = 0
Dönüşümler
Bir demet veya dict, bir dataclass dönüştürme yinelemeli :
>>> dataclasses.astuple(Color(128, 0, 255))
(128, 0, 255)
>>> dataclasses.asdict(Color(128, 0, 255))
{r: 128, g: 0, b: 255}
Sınırlamalar
Referanslar
- R. Hettinger en tartışma üzerine Dataclasses: tüm kod jeneratörleri sona erdirmek için kod üreteci
- T. Hunner konuşma üzerine cruft All olmadan Python Sınıflar: Daha kolay Sınıflar
- Karma ayrıntılarıyla ilgili Python'un belgeleri
- Gerçek Python'un kılavuzu üzerinde Python 3.7 Veri Sınıflara Ultimate Guide
- A. Shaw'un blog yazısı üzerine Python 3.7 veri sınıflarının kısa turu
- E. Smith'in veri sınıfları üzerindeki github deposu
namedtuple
s değişmezdir ve öznitelikler için varsayılan değerlere sahip olamaz, oysa veri sınıfları değiştirilebilir ve bunlara sahip olabilir.