Programmering

Sådan bruges Python-dataglas

Alt i Python er et objekt, eller det siger man siger. Hvis du vil oprette dine egne brugerdefinerede objekter med deres egne egenskaber og metoder, bruger du Pythons klasse modstand mod at få det til at ske. Men at oprette klasser i Python betyder undertiden at skrive masser af gentagne kedelpladekoder for at opsætte klasseinstansen fra de parametre, der sendes til den, eller for at oprette almindelige funktioner som sammenligningsoperatorer.

Dataklasser, introduceret i Python 3.7 (og backportet til Python 3.6), giver en praktisk måde at gøre klasser mindre detaljerede. Mange af de almindelige ting, du laver i en klasse, som at instantere egenskaber fra argumenterne, der sendes til klassen, kan reduceres til et par grundlæggende instruktioner.

Python-dataklasseeksempel

Her er et simpelt eksempel på en konventionel klasse i Python:

klasse Bog:

'' Objekt til sporing af fysiske bøger i en samling. '' '

def __init __ (selv, navn: str, vægt: float, shelf_id: int = 0):

self.name = navn

egenvægt = vægt # i gram til beregning af forsendelse

self.shelf_id = hylde_id

def __repr __ (selv):

returner (f "Book (name = {self.name! r},

vægt = {self.weight! r}, shelf_id = {self.shelf_id! r}) ")

Den største hovedpine her er den måde, hvorpå hvert af argumenterne overføres til__i det__ skal kopieres til objektets egenskaber. Dette er ikke så slemt, hvis du kun har at gøre medBestil, men hvad nu hvis du skal håndtereBogreolBibliotekLager, og så videre? Plus, jo mere kode du skal skrive i hånden, jo større er chancerne for, at du laver en fejl.

Her er den samme Python-klasse, implementeret som en Python-dataklasse:

fra dataclasses importere dataclass @dataclass class Bog: '' 'Objekt til sporing af fysiske bøger i en samling.' '' navn: str vægt: float shelf_id: int = 0 

Når du angiver egenskaber, kaldesfelter, i en dataklasse,@dataclass genererer automatisk al den kode, der er nødvendig for at initialisere dem. Det bevarer også typeoplysningerne for hver ejendom, så hvis du bruger en kodelinter sommypy, det vil sikre, at du leverer de rigtige typer variabler til klassekonstruktøren.

En anden ting@dataclass gør bag kulisserne automatisk oprette kode til et antal almindelige dundermetoder i klassen. I den konventionelle klasse ovenfor måtte vi skabe vores egne__repr__. I dataklassen er dette unødvendigt;@dataclass genererer__repr__ for dig.

Når en dataklasse er oprettet, er den funktionelt identisk med en almindelig klasse. Der er ingen præstationsstraffe for brug af en dataklasse, bortset fra dekoratørens minimale omkostninger, når de erklærer klassedefinitionen.

Tilpas Python-dataklassefelter medMark fungere

Standardmåden, hvorpå dataklasser fungerer, skal være okay for de fleste brugssager. Nogle gange er du dog nødt til at finjustere, hvordan felterne i din dataklasse initialiseres. For at gøre dette kan du brugeMark fungere.

fra dataklasser importerer dataklasse, felt fra indtastning import Liste @dataclass klasse Bog: '' 'Objekt til sporing af fysiske bøger i en samling.' '' navn: str betingelse: str = felt (sammenlign = Falsk) vægt: float = felt (standard = 0.0, repr = Falsk) shelf_id: int = 0 kapitler: Liste [str] = felt (standard_fabrik = liste) 

Når du indstiller en standardværdi til en forekomst afMark, det ændrer, hvordan feltet er konfigureret, afhængigt af hvilke parametre du angiverMark. Dette er de mest anvendte muligheder for Mark (der er andre):

  • Standard: Indstiller standardværdien for feltet. Du skal bruge Standard hvis du a) brugerMark for at ændre andre parametre for feltet, og b) du ønsker at indstille en standardværdi på feltet oven på det. I dette tilfælde bruger viStandard at sættevægt til0.0.
  • standard_fabrik: Angiver navnet på en funktion, der ikke tager nogen parametre, der returnerer et objekt for at fungere som standardværdien for feltet. I dette tilfælde ønsker vi detkapitler at være en tom liste.
  • repr: Som standard (Rigtigt), styrer om det pågældende felt vises i det automatisk genererede__repr__ til dataklassen. I dette tilfælde ønsker vi ikke, at bogens vægt vises i__repr__, så vi brugerrepr = Falsk at udelade det.
  • sammenligne: Som standard (Rigtigt), inkluderer feltet i de sammenligningsmetoder, der automatisk genereres til dataklassen. Her ønsker vi ikketilstand skal bruges som en del af sammenligningen for to bøger, så vi sættersammenligne =Falsk.

Bemærk, at vi har været nødt til at justere rækkefølgen af ​​felterne, så ikke-standardfelterne kommer først.

Brug__post_init__ til at kontrollere initialisering af Python-dataklasse

På dette tidspunkt undrer du dig sandsynligvis: Hvis__i det__ metode til en dataklasse genereres automatisk, hvordan får jeg kontrol over init-processen til at foretage mere detaljerede ændringer?

Gå ind i__post_init__ metode. Hvis du inkluderer__post_init__ metode i din dataklassedefinition, kan du give instruktioner til ændring af felter eller andre instansdata.

fra dataklasser importerer dataklasse, felt fra at skrive import Liste @dataclass klasse Bog: '' 'Objekt til sporing af fysiske bøger i en samling.' '' navn: str vægt: float = felt (standard = 0.0, repr = Falsk) shelf_id: int = felt (init = Falsk) kapitler: Liste [str] = felt (standard_fabrik = liste) tilstand: str = felt (standard = "God", sammenlign = Falsk) def __post_init __ (selv): hvis selvbetingelse == "Kasseres ": self.shelf_id = Ingen andre: self.shelf_id = 0 

I dette eksempel har vi oprettet en__post_init__ metode til at indstille hylde_id tilIngen hvis bogens tilstand initialiseres som"Kasseret". Bemærk hvordan vi brugerMark at initialiserehylde_id, og beståi det somFalsk tilMark. Det betyderhylde_id initialiseres ikke i__i det__.

BrugInitVar for at kontrollere Python-datakladsinitialisering

En anden måde at tilpasse Python-dataklasseopsætning er at brugeInitVar type. Dette giver dig mulighed for at angive et felt, der skal sendes til__i det__ og derefter til__post_init__, men gemmes ikke i klasseinstansen.

Ved hjælp af InitVar, kan du tage parametre, når du konfigurerer dataklassen, der kun bruges under initialisering. Et eksempel:

fra dataklasser importerer dataklasse, felt, InitVar fra at skrive import Liste @dataclass klasse Bog: '' 'Objekt til sporing af fysiske bøger i en samling.' '' navn: str betingelse: InitVar [str] = Ingen vægt: float = felt (standard = 0.0, repr = False) shelf_id: int = field (init = False) kapitler: Liste [str] = field (default_factory = list) def __post_init __ (self, condition): if condition == "Discarded": self.shelf_id = Ingen andre: self.shelf_id = 0 

Indstiller feltets type tilInitVar (med undertype som den faktiske feltype) signalerer til@dataclass ikke at gøre dette felt til et dataklassefelt, men at videregive dataene til__post_init__ som et argument.

I denne version af voresBestil klasse lagrer vi ikketilstand som et felt i klasseinstansen. Vi bruger kun tilstand i initialiseringsfasen. Hvis vi finder dettilstand blev sat til"Kasseret", vi satte oshylde_id tilIngen - men vi gemmer ikketilstand i klasseinstansen.

Hvornår skal man bruge Python-dataklasser - og hvornår man ikke skal bruge dem

Et almindeligt scenario for brug af dataklasser er som erstatning for den navngivne duple. Dataklasser tilbyder samme adfærd og mere, og de kan gøres uforanderlige (som navngivne templer er) ved blot at bruge@dataclass (frossen = sand) som dekoratør.

En anden mulig brugssag er at erstatte indlejrede ordbøger, som kan være klodset at arbejde med, med indlejrede forekomster af dataklasser. Hvis du har en dataklasseBibliotek, med en listeegenskabhylder, kan du bruge en dataklasseReadingRoom at udfylde listen og derefter tilføje metoder for at gøre det let at få adgang til indlejrede genstande (f.eks. en bog på en hylde i et bestemt rum).

Men ikke alle Python-klasser skal være en dataklasse. Hvis du opretter en klasse hovedsageligt som en måde at gruppere en massestatiske metoder, i stedet for som en container til data, behøver du ikke gøre det til en dataklasse. For eksempel er et almindeligt mønster med parsere at have en klasse, der tager et abstrakt syntaks-træ, går i træet og sender opkald til forskellige metoder i klassen baseret på nodetypen. Da parserklassen har meget få egne data, er en dataklasse ikke nyttig her.

Sådan gør du mere med Python

  • Kom godt i gang med async i Python
  • Sådan bruges asyncio i Python
  • Sådan bruges PyInstaller til at oprette Python-eksekverbare filer
  • Cython tutorial: Sådan fremskyndes Python
  • Sådan installeres Python på den smarte måde
  • Sådan styres Python-projekter med Poetry
  • Sådan styres Python-projekter med Pipenv
  • Virtualenv og venv: Python virtuelle miljøer forklaret
  • Python virtualenv og venv do's and don'ts
  • Python-gevind og underprocesser forklaret
  • Sådan bruges Python debugger
  • Sådan bruges timeit til at profilere Python-kode
  • Sådan bruges cProfile til profilering af Python-kode
  • Sådan konverteres Python til JavaScript (og tilbage igen)
$config[zx-auto] not found$config[zx-overlay] not found