Python Încapsulare
Scopul încapsulării este să protejeze datele din interiorul unei clase.
O clasă își ține datele (proprietățile) și metodele într-un singur loc și decide cum poate ajunge la acele date codul din afara clasei.
Drept urmare, datele sunt mai greu de modificat din greșeală, iar funcționarea internă a clasei rămâne ascunsă.
Proprietăți private
Începe numele unei proprietăți cu un dublu underscore, __, iar Python o tratează ca privată:
Notă: Codul din afara clasei nu are acces direct la o proprietate privată.
Exemplu
O clasă cu o proprietate privată numită __age:
Ieșire: program Python complet
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age # Proprietate privată
p1 = Person("Emil", 25)
print(p1.name)
print(p1.__age) # Acest lucru va provoca o eroare
Obținerea valorii unei proprietăți private
O metodă getter îi oferă codului din exterior o modalitate de a citi o proprietate privată:
Exemplu
Citește o proprietate privată printr-o metodă getter:
Ieșire: program Python complet
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age
def get_age(self):
return self.__age
p1 = Person("Tobias", 25)
print(p1.get_age())
Setarea valorii unei proprietăți private
Modificarea unei proprietăți private funcționează la fel, printr-o metodă setter.
O metodă setter poate și să verifice noua valoare înainte de a o stoca:
Exemplu
Schimbă o proprietate privată printr-o metodă setter:
Ieșire: program Python complet
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age
def get_age(self):
return self.__age
def set_age(self, age):
if age > 0:
self.__age = age
else:
print("Vârsta trebuie să fie pozitivă")
p1 = Person("Tobias", 25)
print(p1.get_age())
p1.set_age(26)
print(p1.get_age())
De ce să folosim încapsularea?
Încapsularea îți oferă mai multe avantaje:
- Protecția datelor: Datele sunt ferite de modificări accidentale
- Validare: Valorile noi pot fi verificate înainte de a fi stocate
- Flexibilitate: Codul intern se poate schimba, iar codul din afara clasei continuă să funcționeze
- Control: Doar tu decizi cum sunt citite și modificate datele
Exemplu
Protejează o valoare și verific-o cu ajutorul încapsulării:
Ieșire: program Python complet
class Student:
def __init__(self, name):
self.name = name
self.__grade = 0
def set_grade(self, grade):
if 0 <= grade <= 100:
self.__grade = grade
else:
print("Nota trebuie să fie între 0 și 100")
def get_grade(self):
return self.__grade
def get_status(self):
if self.__grade >= 60:
return "Passed"
else:
return "Failed"
student = Student("Emil")
student.set_grade(85)
print(student.get_grade())
print(student.get_status())
Proprietăți protejate
Pentru proprietățile protejate, Python are o convenție: începe numele cu un singur underscore, _:
Notă: Aceasta este doar o convenție, iar Python nu o impune. _ le semnalează pur și simplu celorlalți programatori că proprietatea este destinată uzului intern.
Exemplu
O clasă cu o proprietate protejată:
Ieșire: program Python complet
class Person:
def __init__(self, name, salary):
self.name = name
self._salary = salary # Proprietate protejată
p1 = Person("Linus", 50000)
print(p1.name)
print(p1._salary) # Se poate accesa, dar nu ar trebui
Metode private
Prefixul cu dublu underscore funcționează și pe metode, făcându-le private:
Notă: O metodă privată se comportă ca o proprietate privată: codul din exterior nu o poate apela direct. Aici, __validate este disponibilă doar pentru alte metode ale clasei.
Exemplu
O clasă cu o metodă privată:
Ieșire: program Python complet
class Calculator:
def __init__(self):
self.result = 0
def __validate(self, num):
if not isinstance(num, (int, float)):
return False
return True
def add(self, num):
if self.__validate(num):
self.result += num
else:
print("Număr invalid")
calc = Calculator()
calc.add(10)
calc.add(5)
print(calc.result)
# calc.__validate(5) # Acest lucru ar provoca o eroare
Name mangling (modificarea numelor)
Name mangling (modificarea numelor) este tehnica pe care o folosește Python pentru a face private proprietățile și metodele.
Un nume care începe cu dublu underscore __ este schimbat discret: Python pune _ClassName în fața lui.
Astfel, __age devine _Person__age.
Notă: Numele modificat îți oferă acces la o proprietate privată (poți să-l folosești), dar ar trebui să eviți asta, pentru că anulează scopul încapsulării.
Exemplu
Uită-te la un nume modificat în acțiune:
Ieșire: program Python complet
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age
p1 = Person("Emil", 30)
# Așa modifică Python numele:
print(p1._Person__age) # Nu este recomandat!