Distincția dintre variabilele de clasă și cele de instanță explicată.
Variabilele sunt, în esență, simboluri care reprezintă o valoare pe care o folosim într-un program. Programarea orientată pe obiecte permite ca variabilele să fie utilizate la nivel de clasă sau la nivel de instanță. Scopul acestui articol este de a face o distincție clară între tipurile de variabile oferite de modelul de obiecte Python’ și merge mai departe pentru a discuta în continuare un comportament ciudat care ar putea duce la unele rezultate surprinzătoare, dacă este neglijat. Așadar, să intrăm în subiect!
Conform modelului de obiect Python, există două tipuri de atribute de date pe obiectele Python: variabile de clasă și variabile de instanță.
Variabile de clasă – Declarate în interiorul definiției clasei (dar în afara oricărei metode de instanță). Ele nu sunt legate de niciun obiect anume al clasei, prin urmare sunt partajate între toate obiectele clasei. Modificarea unei variabile de clasă afectează toate obiectele de instanță în același timp.
Variabilă de instanță – Declarată în interiorul metodei constructor al clasei (metoda __init__
). Ele sunt legate de o anumită instanță de obiect a clasei, prin urmare, conținutul unei variabile de instanță este complet independent de la o instanță de obiect la alta.
Să începem cu un exemplu scurt și ușor de digerat:
class Car:
wheels = 4 # <- Class variable def __init__(self, name):
self.name = name # <- Instance variable
Sus este definită clasa Car de bază, fără complicații. Fiecare instanță a acesteia va avea variabila de clasă wheels împreună cu numele variabilei de instanță. Să instanțiem clasa pentru a accesa variabilele.
>>> jag = Car('jaguar')
>>> fer = Car('ferrari')>>> jag.name, fer.name
('jaguar', 'ferrari')>>> jag.wheels, fer.wheels
(4, 4)>>> Car.wheels
4
Accesul la numele variabilei de instanță este destul de simplu. Cu toate acestea, există un pic mai multă flexibilitate când vine vorba de accesarea variabilei de clasă. Ca și mai sus, putem accesa roțile prin intermediul instanței obiectului sau al clasei în sine.
De asemenea, încercarea de a accesa numele prin intermediul clasei va avea ca rezultat un AttributeError, deoarece variabilele de instanță sunt specifice obiectului și sunt create atunci când este invocat constructorul __init__
. Aceasta este distincția centrală dintre clasa și variabilele de instanță.
>>> Car.name
AttributeError: type object 'Car' has no attribute 'name'
Acum, să presupunem pentru moment că mașina noastră Jaguar are 3 roți. (da, este o prostie, dar aveți răbdare!!! 😅). Pentru a reprezenta acest lucru în codul nostru, putem modifica variabila wheels.
>>> Car.wheels = 3
Ce am făcut mai sus va face ca toate mașinile să aibă 3 roți, deoarece am modificat o variabilă de clasă, care se va aplica tuturor instanțelor clasei Car.
>>> jag.wheels, fer.wheels
(3, 3)
În consecință, modificarea unei variabile de clasă din spațiul de nume al clasei afectează toate instanțele clasei. Să revenim asupra modificării și să modificăm variabila wheels folosind obiectul jag.
>>> Car.wheels = 4
>>> jag.wheels = 3
Aceasta ne va da rezultatul dorit.
>>> jag.wheels, fer.wheels, Car.wheels
(3, 4, 4)
Deși am obținut rezultatul dorit, dar ceea ce s-a întâmplat în spatele scenei este o nouă variabilă wheels care a fost adăugată la obiectul jag și această nouă variabilă umbrește variabila de clasă cu același nume, suprascriind-o și ascunzând-o. Putem accesa ambele variabile wheels ca mai jos.
>>> jag.wheels, jag.__class__.wheels
(3, 4)
De aici putem concluziona că jag.wheels = 3
a creat o nouă variabilă de instanță cu același nume ca și variabila de clasă (wheels). Acesta este un concept important de care trebuie să fim conștienți.
Utilizarea variabilelor specifice clasei și instanței poate asigura că codul nostru aderă la principiul DRY pentru a reduce repetiția în cadrul codului.
Cunoașterea acestui lucru consider că poate fi foarte utilă și poate salva o mulțime de ore de depanare într-o zi. 😇
Referiți-vă la această postare a mea pentru a citi în continuare despre diferitele tipuri de metode (instanță, clasă & statică) în Python.
Concluzii
- Variabilele de clasă sunt partajate între toate obiectele, în timp ce variabilele de instanță sunt pentru date unice pentru fiecare instanță.
- Variabilele de instanță suprascriu variabilele de clasă care au același nume, ceea ce poate introduce accidental erori sau comportamente surprinzătoare în codul nostru.
.