Klasse- vs. instansvariabler

Forklaring på forskellen mellem klasse- og instansvariabler.

Rachit Tayal
Rachit Tayal

Follow

9. jun, 2019 – 3 min læsning

Variabler er i bund og grund symboler, der står for en værdi, som vi bruger i et program. Objektorienteret programmering giver mulighed for at anvende variabler på klasse- eller instansniveau. Formålet med denne artikel er at have en klar skelnen mellem de typer af variabler, som Pythons objektmodel tilbyder, og går videre til yderligere at diskutere en ejendommelig adfærd, der kan føre til nogle overraskende resultater, hvis den negligeres. Så lad os gå i dybden!
Som Pythons objektmodel er der to typer dataattributter på Python-objekter: klassevariabler og instansvariabler.

Klassevariabler – Erklæres inde i klassedefinitionen (men uden for nogen af instansmetoderne). De er ikke bundet til et bestemt objekt i klassen, og deles derfor på tværs af alle klassens objekter. Ændring af en klassevariabel påvirker alle objekter instance på samme tid.

Instancevariabel – Erklæres inde i klassens konstruktionsmetode (__init__-metoden). De er bundet til den bestemte objektinstans af klassen, og derfor er indholdet af en instansvariabel fuldstændig uafhængigt af den ene objektinstans til den anden.

Lad os starte med et kort og letfordøjeligt eksempel:

class Car:
wheels = 4 # <- Class variable def __init__(self, name):
self.name = name # <- Instance variable

Ovenfor er den grundlæggende, ukomplicerede Car-klasse defineret. Hver instans af den vil have klassevariabel hjul sammen med instansvariabelnavnet. Lad os instantiere klassen for at få adgang til variablerne.

>>> jag = Car('jaguar')
>>> fer = Car('ferrari')>>> jag.name, fer.name
('jaguar', 'ferrari')>>> jag.wheels, fer.wheels
(4, 4)>>> Car.wheels
4

Accessing the instance variable name is pretty straight forward. Der er dog lidt mere fleksibilitet, når det drejer sig om at få adgang til klassevariablen. Som ovenfor kan vi få adgang til hjul via objektinstansen eller via selve klassen.

Det vil også resultere i en AttributeError at forsøge at få adgang til navnet via klassen, da instansvariabler er objektspecifikke og oprettes, når __init__ konstruktøren påkaldes. Dette er den centrale sondring mellem klasse- og instansvariabler.

>>> Car.name
AttributeError: type object 'Car' has no attribute 'name'

Nu antager vi for en tid, at vores Jaguar-bil har 3 hjul. (ja, det er dumt, men bær over med det!!! 😅). For at repræsentere det i vores kode kan vi ændre variablen wheels.

>>> Car.wheels = 3

Det vi gjorde ovenfor vil gøre alle biler med 3 hjul, da vi har ændret en klassevariabel, som vil gælde for alle instanser af Car-klassen.

>>> jag.wheels, fer.wheels
(3, 3)

Derfor påvirker ændring af en klassevariabel i klassens navneområde alle instanser af klassen. Lad os rulle ændringen tilbage og ændre hjulvariablen ved hjælp af jag-objektet.

>>> Car.wheels = 4
>>> jag.wheels = 3

Dette vil give os det output, vi ønsker.

>>> jag.wheels, fer.wheels, Car.wheels
(3, 4, 4)

Selv om vi fik det ønskede resultat, men det, der skete bag kulisserne, er en ny hjulvariabel, der er blevet tilføjet til jag-objektet, og denne nye variabel skygger for klassevariablen med samme navn, overstyrer og skjuler den. Vi kan få adgang til begge hjulvariable som nedenfor:

>>> jag.wheels, jag.__class__.wheels
(3, 4)

Deraf kan vi konkludere, at jag.wheels = 3 har oprettet en ny instansvariabel med samme navn som klassevariablen (hjul). Dette er et vigtigt begreb, som det er vigtigt at være opmærksom på.
Gennem at gøre brug af klasse- og instansspecifikke variabler kan vi sikre, at vores kode overholder DRY-princippet for at reducere gentagelser i koden.
Ved dette føler jeg, at det kan være rigtig praktisk og spare mange timers fejlfinding en dag. 😇
Referer til mit dette indlæg for at læse yderligere om forskellige slags metoder (instance, class & static) i Python.

Konklusioner

  • Klassevariabler deles på tværs af alle objekter, mens instancevariabler er til data, der er unikke for hver enkelt instans.
  • Instancevariable overstyrer klassevariabler med samme navn, hvilket ved et uheld kan indføre fejl eller overraskende adfærd i vores kode.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.