Python’daki her şey bir nesnedir, ya da öyle söylenir. Kendi özellikleri ve yöntemleriyle kendi özel nesnelerinizi oluşturmak istiyorsanız, Python’u kullanırsınız. class
bunun gerçekleşmesi için itiraz edin. Ancak Python’da sınıf oluşturmak bazen, kendisine iletilen parametrelerden sınıf örneğini ayarlamak veya karşılaştırma işleçleri gibi ortak işlevler oluşturmak için bir sürü tekrarlayan, standart kod yazmak anlamına gelir.
Python 3.7’de tanıtılan veri sınıfları (ve Python 3.6’ya desteklendi), sınıflar oluşturmak için kullanışlı, daha az ayrıntılı bir yol sağlar. Sınıfa iletilen bağımsız değişkenlerden özellikleri somutlaştırmak gibi bir sınıfta yaptığınız yaygın şeylerin çoğu birkaç temel talimata indirgenebilir.
Python veri sınıfı örneği
İşte Python’da geleneksel bir sınıfın basit bir örneği:
class Book:
'''Object for tracking physical books in a collection.'''
def __init__(self, name: str, weight: float, shelf_id:int = 0):
self.name = name
self.weight = weight # in grams, for calculating shipping
self.shelf_id = shelf_id
def __repr__(self):
return(f"Book(name={self.name!r},
weight={self.weight!r}, shelf_id={self.shelf_id!r})")
Buradaki en büyük baş ağrısı, argümanların her birinin __init__
nesnenin özelliklerine kopyalanmalıdır. Sadece bunlarla uğraşıyorsan bu o kadar da kötü değil Book
ama ya uğraşmak zorunda kalırsan Bookshelf
, Library
, Warehouse
, ve benzeri? Ayrıca, elle yazmanız gereken kod sayısı arttıkça hata yapma olasılığınız da artar.
İşte bir Python veri sınıfı olarak uygulanan aynı Python sınıfı:
from dataclasses import dataclass
@dataclass
class Book:
'''Object for tracking physical books in a collection.'''
name: str
weight: float
shelf_id: int = 0
Özellikleri belirttiğinizde, çağrılan alanlar, bir veri sınıfında, @dataclass
dekoratör, bunları başlatmak için gereken tüm kodu otomatik olarak üretir. Ayrıca her özellik için tür bilgisini de korur, bu nedenle linter gibi bir kod kullanırsanız mypy
sınıf kurucusuna doğru türde değişkenler sağladığınızdan emin olacaktır.
Başka bir şey @dataclass
perde arkasında, sınıftaki bir dizi yaygın dunder yöntemi için otomatik olarak kod oluşturur. Yukarıdaki geleneksel sınıfta, kendi sınıfımızı yaratmamız gerekiyordu. __repr__
. Veri sınıfında, @dataclass
dekoratör oluşturur __repr__
senin için.
Bir veri sınıfı oluşturulduktan sonra, işlevsel olarak normal bir sınıfla aynıdır. Bir veri sınıfı kullanmak için herhangi bir performans cezası yoktur. Sınıfı bir veri sınıfı olarak bildirmenin yalnızca küçük bir performans cezası vardır ve bu, veri sınıfı nesnesi oluşturulduğunda tek seferlik bir maliyettir.
Gelişmiş Python veri sınıfı başlatma
dataclass dekoratör alabilir kendi başlatma seçenekleri. Çoğu zaman bunları sağlamanız gerekmez, ancak belirli uç durumlar için kullanışlı olabilirler. İşte en yararlı olanlardan bazıları (hepsi True/False
):
frozen
: Salt okunur sınıf örnekleri oluşturur. Veriler atandıktan sonra değiştirilemez.slots
: Yalnızca sınıfta açıkça tanımlanan alanlara izin vererek veri sınıfı örneklerinin daha az bellek kullanmasına izin verir.kw_only
: Ayarlandığında, sınıf için tüm alanlar yalnızca anahtar kelimedir.
Python veri sınıfı alanlarını şu şekilde özelleştirin: field
işlev
Veri sınıflarının varsayılan çalışma şekli, kullanım durumlarının çoğu için uygun olmalıdır. Ancak bazen, veri sınıfınızdaki alanların nasıl başlatılacağı konusunda ince ayar yapmanız gerekir. Aşağıda gösterildiği gibi, kullanabilirsiniz field
ince ayar işlevi:
from dataclasses import dataclass, field
from typing import List
@dataclass
class Book:
'''Object for tracking physical books in a collection.'''
name: str
condition: str = field(compare=False)
weight: float = field(default=0.0, repr=False)
shelf_id: int = 0
chapters: List[str] = field(default_factory=list)
Örneğine varsayılan bir değer ayarladığınızda field
hangi parametreleri verdiğinize bağlı olarak alanın nasıl kurulduğunu değiştirir field
. Bunlar en sık kullanılan seçeneklerdir. field
(başkaları da var):
default
: Alan için varsayılan değeri ayarlar. kullanman gerekdefault
eğer a) kullanırsanfield
alan için diğer parametreleri değiştirmek ve b) bunun üzerine alan üzerinde varsayılan bir değer ayarlamak istemek. Bu durumda, kullanırızdefault
kurmakweight
ile0.0
.default_factory
: Alan için varsayılan değer olarak işlev görecek bir nesne döndüren, hiçbir parametre almayan bir işlevin adını sağlar. Bu durumda istediğimizchapters
boş bir liste olmak.repr
: Varsayılan olarak (True
), söz konusu alanın otomatik olarak oluşturulan ekranda görünüp görünmediğini kontrol eder.__repr__
veri sınıfı için. Bu durumda kitabın ağırlığının ekranda gösterilmesini istemiyoruz.__repr__
bu yüzden kullanıyoruzrepr=False
atlamak için.compare
: Varsayılan olarak (True
), veri sınıfı için otomatik olarak oluşturulan karşılaştırma yöntemlerindeki alanı içerir. İşte istemiyoruzcondition
iki kitap için karşılaştırmanın bir parçası olarak kullanılacak, bu yüzden belirledikcompare=False
.
Varsayılan olmayan alanların önce gelmesi için alanların sırasını ayarlamak zorunda kaldığımıza dikkat edin.
Python veri sınıfı başlatmayı denetleme
Bu noktada muhtemelen şunu merak ediyorsunuz: __init__
bir veri sınıfı yöntemi otomatik olarak oluşturulur, daha ayrıntılı değişiklikler yapmak için başlatma işlemi üzerinde nasıl kontrol sahibi olurum?
__post_init__
Giriş __post_init__
yöntem. eklerseniz __post_init__
yöntemini kullanarak, alanları veya diğer örnek verilerini değiştirmek için talimatlar sağlayabilirsiniz:
from dataclasses import dataclass, field
from typing import List
@dataclass
class Book:
'''Object for tracking physical books in a collection.'''
name: str
weight: float = field(default=0.0, repr=False)
shelf_id: Optional[int] = field(init=False)
chapters: List[str] = field(default_factory=list)
condition: str = field(default="Good", compare=False)
def __post_init__(self):
if self.condition == "Discarded":
self.shelf_id = None
else:
self.shelf_id = 0
Bu örnekte, bir __post_init__
ayarlama yöntemi shelf_id
ile None
kitabın durumu şu şekilde başlatılırsa "Discarded"
. nasıl kullandığımıza dikkat edin field
başlatmak için shelf_id
ve geç init
gibi False
ile field
. Bunun anlamı shelf_id
başlatılmayacak __init__
.
InitVar
Python veri sınıfı kurulumunu özelleştirmenin başka bir yolu da InitVar
tip. Bu, geçirilecek bir alan belirtmenizi sağlar. __init__
ve sonra __post_init__
ancak sınıf örneğinde saklanmaz.
Kullanarak InitVar
, yalnızca başlatma sırasında kullanılan veri sınıfını kurarken parametreleri alabilirsiniz. İşte bir örnek:
from dataclasses import dataclass, field, InitVar
from typing import List
@dataclass
class Book:
'''Object for tracking physical books in a collection.'''
name: str
condition: InitVar[str] = "Good"
weight: float = field(default=0.0, repr=False)
shelf_id: int = field(init=False)
chapters: List[str] = field(default_factory=list)
def __post_init__(self, condition):
if condition == "Unacceptable":
self.shelf_id = None
else:
self.shelf_id = 0
Bir alanın türünü şu şekilde ayarlama InitVar
(alt tipi gerçek alan tipidir) sinyal verir: @dataclass
bu alanı bir veri sınıfı alanına dönüştürmek değil, verileri __post_init__
bir argüman olarak.
Bu versiyonumuzda Book
sınıf, depolamıyoruz condition
sınıf örneğinde bir alan olarak. sadece kullanıyoruz condition
başlatma aşamasında. Eğer onu bulursak condition
ayarlandı "Unacceptable"
ayarladık shelf_id
ile None
— ama biz saklamayız condition
sınıf örneğinde kendisi.
Python veri sınıfları ne zaman kullanılır ve ne zaman kullanılmaz
Veri sınıflarını kullanmak için yaygın bir senaryo şudur: için bir yedek adlandırılmış. Veri sınıfları aynı davranışları ve daha fazlasını sunar ve değiştirilemez hale getirilebilir (örneğin, namedtuple
s) basitçe kullanarak @dataclass(frozen=True)
dekoratör olarak.
Başka bir olası kullanım durumu ise iç içe geçmiş sözlükleri değiştirmeiç içe geçmiş veri sınıfları örnekleriyle çalışmak beceriksiz olabilir. Bir veri sınıfınız varsa Library
list özelliği ile shelves
bir veri sınıfı kullanabilirsiniz ReadingRoom
bu listeyi doldurmak için, ardından iç içe geçmiş öğelere (örneğin, belirli bir odadaki raftaki bir kitap) erişimi kolaylaştıracak yöntemler ekleyin.
Ancak her Python sınıfının bir veri sınıfı olması gerekmez. Bir sınıfı, veriler için bir kapsayıcı olarak değil, bir grup statik yöntemi bir araya getirmenin bir yolu olarak oluşturuyorsanız, onu bir veri sınıfı yapmanıza gerek yoktur. Örneğin, ayrıştırıcılarla ortak bir model, soyut bir sözdizimi ağacını alan, ağaçta yürüyen ve düğüm türüne göre sınıftaki farklı yöntemlere çağrılar gönderen bir sınıfa sahip olmaktır. Ayrıştırıcı sınıfının kendine ait çok az verisi olduğundan, burada bir veri sınıfı kullanışlı değildir.
Telif hakkı © 2023 IDG Communications, Inc.
Kaynak : https://www.infoworld.com/article/3563878/how-to-use-python-dataclasses.html#tk.rss_all