Programmering

Hvordan bruke Python dataklasser

Alt i Python er et objekt, eller så sier ordtaket. Hvis du vil lage dine egne egendefinerte objekter, med egne egenskaper og metoder, bruker du Pythons klasse innvending for å få det til. Men å opprette klasser i Python betyr noen ganger å skrive massevis av repeterende kokerplatekode for å sette opp klasseinstansen fra parametrene som sendes til den, eller for å lage vanlige funksjoner som sammenligningsoperatorer.

Dataklasser, introdusert i Python 3.7 (og backported til Python 3.6), gir en praktisk måte å gjøre klassene mindre detaljerte. Mange av de vanligste tingene du gjør i en klasse, som å sette i gang egenskaper fra argumentene som sendes til klassen, kan reduseres til noen få grunnleggende instruksjoner.

Python dataklasseeksempel

Her er et enkelt eksempel på en konvensjonell klasse i Python:

class Book:

'' 'Objekt for sporing av fysiske bøker i en samling.' ''

def __init __ (selv, navn: str, vekt: float, shelf_id: int = 0):

self.name = navn

egenvekt = vekt # i gram, for beregning av frakt

self.shelf_id = shelf_id

def __repr __ (selv):

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

vekt = {self.weight! r}, shelf_id = {self.shelf_id! r}) ")

Den største hodepinen her er måten hvert av argumentene overføres til__i det__ må kopieres til objektets egenskaper. Dette er ikke så ille hvis du bare har å gjøre medBok, men hva om du må forholde deg tilBokhylleBibliotekLager, og så videre? Dessuten, jo mer kode du må skrive for hånd, jo større er sjansene for at du tar feil.

Her er den samme Python-klassen, implementert som en Python-dataklasse:

fra dataclasses importer dataclass @dataclass class Bok: '' 'Objekt for sporing av fysiske bøker i en samling.' '' navn: str vekt: float shelf_id: int = 0 

Når du spesifiserer egenskaper, kaltEnger, i en dataklasse,@dataclass genererer automatisk all koden som trengs for å initialisere dem. Det bevarer også typeinformasjonen for hver eiendom, så hvis du bruker en kodelinter sommypy, vil det sikre at du leverer de riktige variablene til klassekonstruktøren.

En annen ting@dataclass gjør bak kulissene er å automatisk lage kode for en rekke vanlige dundermetoder i klassen. I den konvensjonelle klassen ovenfor måtte vi lage våre egne__repr__. I dataklassen er dette unødvendig;@dataclass genererer__repr__ for deg.

Når en dataklasse er opprettet, er den funksjonelt identisk med en vanlig klasse. Det er ingen ytelsesstraff for å bruke en dataklasse, bortsett fra den minimale kostnaden for dekoratøren når man erklærer klassedefinisjonen.

Tilpass Python dataklassefelt medfelt funksjon

Standard måten dataklasser fungerer på, bør være greit for de fleste brukssaker. Noen ganger må du finjustere hvordan feltene i dataklassen din initialiseres. For å gjøre dette kan du brukefelt funksjon.

fra dataklasser importerer dataklasse, felt fra å skrive import Liste @dataclass klasse Bok: '' 'Objekt for sporing av fysiske bøker i en samling.' '' navn: str tilstand: str = felt (sammenlign = Falsk) vekt: float = felt (standard = 0.0, repr = False) shelf_id: int = 0 kapitler: Liste [str] = felt (default_factory = liste) 

Når du angir en standardverdi til en forekomst avfelt, det endrer hvordan feltet er satt opp avhengig av hvilke parametere du girfelt. Dette er de mest brukte alternativene for felt (det er andre):

  • misligholde: Angir standardverdien for feltet. Du må bruke misligholde hvis du a) brukerfelt for å endre andre parametere for feltet, og b) du vil angi en standardverdi på feltet på toppen av det. I dette tilfellet bruker vimisligholde å settevekt til0.0.
  • standard_fabrikk: Gir navnet på en funksjon, som ikke tar noen parametere, som returnerer noe objekt for å fungere som standardverdien for feltet. I dette tilfellet vil vikapitler å være en tom liste.
  • repr: Som standard (ekte), kontrollerer om det aktuelle feltet vises i det automatisk genererte__repr__ for dataklassen. I dette tilfellet ønsker vi ikke at bokens vekt vises i__repr__, så vi brukerrepr = Falsk å utelate det.
  • sammenligne: Som standard (ekte), inkluderer feltet i sammenligningsmetodene som automatisk genereres for dataklassen. Her vil vi ikketilstand skal brukes som en del av sammenligningen for to bøker, så vi settersammenligne =Falsk.

Merk at vi har måttet justere rekkefølgen på feltene slik at ikke-standardfeltene kommer først.

Bruk__post_init__ for å kontrollere initialisering av Python-dataklasse

På dette punktet lurer du sannsynligvis på: Hvis__i det__ metoden til en dataklasse genereres automatisk, hvordan får jeg kontroll over init-prosessen for å gjøre mer detaljerte endringer?

Skriv inn__post_init__ metode. Hvis du inkluderer__post_init__ metode i dataklasse-definisjonen din, kan du gi instruksjoner for å endre felt eller andre forekomstdata.

fra dataklasser importerer dataklasse, felt fra å skrive import Liste @dataclass klasse Bok: '' 'Objekt for sporing av fysiske bøker i en samling.' '' navn: str vekt: float = felt (standard = 0.0, repr = Falsk) shelf_id: int = felt (init = Falsk) kapitler: Liste [str] = felt (standard_fabrikk = liste) tilstand: str = felt (standard = "Bra", sammenlign = Falsk) def __post_init __ (selv): hvis selvbetingelse == "Forkastet ": self.shelf_id = Ingen andre: self.shelf_id = 0 

I dette eksemplet har vi opprettet en__post_init__ metode for å sette shelf_id tilIngen hvis bokens tilstand initialiseres som"Forkastet". Legg merke til hvordan vi brukerfelt å initialisereshelf_id, og passerei det somFalsk tilfelt. Dette betyrshelf_id vil ikke bli initialisert i__i det__.

BrukInitVar for å kontrollere initialisering av Python-dataklasse

En annen måte å tilpasse Python dataklasseoppsett på er å brukeInitVar type. Dette lar deg spesifisere et felt som skal sendes til__i det__ og deretter til__post_init__, men lagres ikke i klasseinstansen.

Ved bruk av InitVar, kan du ta inn parametere når du setter opp dataklassen som bare brukes under initialisering. Et eksempel:

fra dataklasser importerer dataklasse, felt, InitVar fra å skrive import Liste @dataclass klasse Bok: '' 'Objekt for sporing av fysiske bøker i en samling.' '' navn: str tilstand: InitVar [str] = Ingen vekt: 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 == "Forkastet": self.shelf_id = Ingen andre: self.shelf_id = 0 

Setter feltets type tilInitVar (med undertype som den faktiske feltypen) signaliserer til@dataclass å ikke gjøre det feltet til et dataklassefelt, men å overføre dataene til__post_init__ som argument.

I denne versjonen av vårBok klasse lagrer vi ikketilstand som et felt i klasseinstansen. Vi bruker bare tilstand under initialiseringsfasen. Hvis vi finner dettilstand ble satt til"Forkastet", vi settershelf_id tilIngen - men vi lagrer ikketilstand i klasseinstansen.

Når skal du bruke Python-dataklasser - og når ikke å bruke dem

Et vanlig scenario for bruk av dataklasser er som erstatning for navngitt tuple. Databriller har samme oppførsel og mer, og de kan gjøres uforanderlige (som navngitte tinninger er) ved å bare bruke@dataclass (frossen = sann) som dekoratør.

En annen mulig brukssak er å erstatte nestede ordbøker, som kan være klønete å jobbe med, med nestede forekomster av dataklasser. Hvis du har en dataklasseBibliotek, med en listeegenskaphyller, kan du bruke en dataklasseLeserom å fylle ut listen, og deretter legge til metoder for å gjøre det enkelt å få tilgang til nestede gjenstander (f.eks. en bok på en hylle i et bestemt rom).

Men ikke alle Python-klasser trenger å være en dataklasse. Hvis du oppretter en klasse hovedsakelig som en måte å gruppere en haug medstatiske metoder, i stedet for som en beholder for data, trenger du ikke gjøre det til en dataklasse. For eksempel er et vanlig mønster med parsere å ha en klasse som tar et abstrakt syntaks-tre, går i treet og sender anrop til forskjellige metoder i klassen basert på nodetypen. Fordi parserklassen har svært lite data, er en dataklasse ikke nyttig her.

Hvordan gjøre mer med Python

  • Kom i gang med asynkronisering i Python
  • Hvordan bruke asyncio i Python
  • Hvordan bruke PyInstaller for å lage Python-kjørbare filer
  • Cython tutorial: Hvordan øke hastigheten på Python
  • Slik installerer du Python på den smarte måten
  • Hvordan håndtere Python-prosjekter med poesi
  • Hvordan administrere Python-prosjekter med Pipenv
  • Virtualenv og venv: Python virtuelle miljøer forklart
  • Python virtualenv og venv do’s and don'ts
  • Python-tråder og underprosesser forklart
  • Hvordan bruke Python-feilsøkingsprogrammet
  • Hvordan bruke timeit til å profilere Python-kode
  • Hvordan bruke cProfile for å profilere Python-kode
  • Slik konverterer du Python til JavaScript (og tilbake igjen)
$config[zx-auto] not found$config[zx-overlay] not found