Osztály- és példányváltozók

Magyarázat az osztály- és példányváltozók közötti különbségtételre.

Rachit Tayal
Rachit Tayal

Follow

Jun 9, 2019 – 3 min read

A változók lényegében olyan szimbólumok, amelyek egy általunk használt értéket helyettesítenek a programban. Az objektumorientált programozás lehetővé teszi, hogy a változókat osztály- vagy példányszinten használjuk. A cikk célja, hogy egyértelmű különbséget tegyünk a Python objektummodellje által kínált változók típusai között, és a továbbiakban egy olyan sajátos viselkedést tárgyalunk, amelynek elhanyagolása meglepő eredményekhez vezethet. Tehát ássunk bele!
A Python objektummodellje szerint kétféle adatattribútum létezik a Python-objektumokon: az osztályváltozók és a példányváltozók.

Osztályváltozók – Az osztály definícióján belül (de a példánymódszereken kívül) deklaráltak. Nem kötődnek az osztály egyetlen konkrét objektumához sem, ezért az osztály összes objektuma számára közösek. Az osztályváltozó módosítása egyszerre érinti az összes objektum példányát.

Instance Variable – Az osztály konstruktor metódusán (a __init__ metóduson) belül deklarált. Az osztály adott objektumpéldányához kötődnek, ezért egy példányváltozó tartalma teljesen független az egyik objektumpéldánytól a másikig.

Kezdjük egy rövid és könnyen emészthető példával:

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

Fentebb az alapvető, sallangmentes Car osztály van definiálva. Minden példányának a példányváltozó neve mellett lesz osztályváltozója a kerekek. Pusztítsuk el az osztályt, hogy hozzáférjünk a változókhoz.

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

A példányváltozó nevének elérése elég egyszerű. Az osztályváltozó elérésekor azonban egy kicsit rugalmasabbak vagyunk. A fentiekhez hasonlóan elérhetjük a kerekeket az objektum példányán vagy magán az osztályon keresztül.

Az osztályon keresztül történő névelérés megkísérlése szintén AttributeError-t eredményez, mivel a példányváltozók objektum specifikusak és a __init__ konstruktor meghívásakor jönnek létre. Ez a központi különbségtétel az osztály és a példányváltozók között.

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

Most tegyük fel egyelőre, hogy a Jaguár autónknak 3 kereke van. (igen, ez hülyeség, de viseljük el!!! 😅). Ahhoz, hogy ezt megjelenítsük a kódunkban, módosíthatjuk a wheels változót.

>>> Car.wheels = 3

Amiatt, amit fentebb tettünk, minden autónak 3 kereke lesz, mivel egy osztályváltozót módosítottunk, ami a Car osztály minden példányára vonatkozik.

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

Ezért egy osztályváltozó módosítása az osztály névterében az osztály minden példányára hatással van. Vegyük vissza a módosítást, és módosítsuk a kerekek változót a jag objektummal.

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

Ez a kívánt eredményt fogja adni.

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

Mégis megkaptuk a kívánt eredményt, de a színfalak mögött az történt, hogy a jag objektumhoz egy új kerekek változó került hozzá, és ez az új változó árnyékolja az azonos nevű osztályváltozót, felülírja és elrejti azt. Mindkét wheels változóhoz az alábbiak szerint férhetünk hozzá:

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

Ez alapján megállapíthatjuk, hogy a jag.wheels = 3 létrehozott egy új példányváltozót, amelynek neve megegyezik az osztályváltozóéval (wheels). Ez egy fontos fogalom, amivel tisztában kell lennünk.
Az osztály- és példányspecifikus változók használatával biztosíthatjuk, hogy a kódunk betartsa a DRY elvét, hogy csökkentsük a kódon belüli ismétlődéseket.
Ezek ismerete úgy érzem, igazán hasznos lehet, és sok órányi hibakeresést takaríthat meg egy nap. 😇
A Python különböző típusú metódusairól (instance, class & static) bővebben ebben a bejegyzésemben olvashat.

Következtetések

  • Az osztályváltozókat minden objektum megosztja, míg a instance változók az egyes példányok egyedi adataihoz tartoznak.
  • A instance változó felülírja az azonos nevű osztályváltozókat, ami véletlenül hibákat vagy meglepő viselkedést hozhat a kódunkban.

.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.