Tema 9, Python
Tema 9, Python
class Butterfly:
'''I have created a class Butterfly'''
name = "Skipper"
• Am utilizat cuvântul rezervat class, pentru a defini clasa Butterfly. În baza clasei vom putea construi obiecte sau exemplare ale clasei
• Un exemplar al clasei – este un anumit obiect, creat în baza unei anumite clase
DEFINIREA UNEI CLASE ÎN PYTHON
• Odată definită clasa, se va crea un spațiu de nume local, în care vor fi definite toate atributele clasei. În Python atributele pot fi date
sau funcții
• Există atribute speciale în Python, de exemplu cele care încep cu două liniuțe de subliniere (__), precum __doc__ - care ne permite
accesul la liniile de documentare ale clasei curente
• Cum numai vom defini clasa, automat se va crea și un nou obiect cu același nume. Acest obiect definit de clasă ne va permite să
accesăm diferite atribute ale clasei, dar și să creăm alte obiecte, noi, în baza clasei
• Exemplu:
class Butterfly:
'''My first class'''
name = "Skipper"
print(Butterfly.__doc__)
CUVÂNTUL REZERVAT PASS
• În Python cuvântul rezervat sau instrucțiunea «pass», este folosit pentru a specifica ”că nu se-ntâmplă nimic”
• Instrucțiunea pass este utilizată, de obicei, atunci când avem necesitatea definirii funcțiilor, claselor și
ciclurilor vide
• Cu ajutorul pass – vom specifica un bloc fără conținut. Instrucțiunea poate fi plasată din rând nou sau pe
aceeași linie în care se definește clasa, ciclul, funcția etc.
• Exemplu de creare a unei clase vide:
class Batterfly:
pass
MODIFICATORI DE ACCES: PUBLIC, PRIVAT ȘI
PROTEJAT
• Limbajele clasice orientate pe obiecte, precum C ++ sau Java, controlează accesul la resursele clasei prin cuvintele cheie:
public, private și protected
Ne reamintim!
• La membrii privați ai unei clase - este interzis accesul din mediul extern clasei. Aceștia pot fi gestionați doar din interiorul
clasei
• Membrii publici (în general, metodele declarate într-o clasă) sunt accesibili din afara clasei. Doar obiectul aceleiași clase
poate invoca o metodă publică
• Convenția prin care variabilele trebuie să fie private, iar metodele – publice, asigură principiul încapsulării datelor!
• Membrii protejați ai unei clase sunt accesibili din interiorul clasei și sunt, de asemenea, disponibili pentru clasele sale
urmași. Nici dintr-un alt mediu nu este permis accesul la aceștia. Acest lucru permite ca resursele specifice ale clasei părinte
să fie moștenite de clasa-urmaș
DEFINIREA ATRIBUTELOR PUBLICE
• Python nu are nici un mecanism care restricționează efectiv accesul la orice variabilă sau metodă a instanței
• Python dispune, însă, de o convenție de prefixare a denumirilor variabilelor și metodelor cu o liniuță de subliniere sau două,
pentru a imita comportamentul specificatorilor de acces protejat și privat
• Toți membrii dintr-o clasă Python sunt publici în mod implicit. Orice membru poate fi accesat din afara mediului definit de
clasă
• Exemplu:
class employee:
def __init__(self, name, sal):
self.name=name # public atributte
self.salary=sal
empl = employee("Nelu", 8000)
print(empl.name + " have " + str(empl.salary))
REDEFINIREA ATRIBUTELOR PROTECTED
• Convenția Python de a face ca o variabilă a instanței să fie protejată este să se adauge un prefix _ (un simbol
de subliniere)
• Acest lucru împiedică efectiv accesarea acestuia, cu excepția cazului în care accesul se face dintr-o clasă-urmaș
• Exemplu:
class employee:
def __init__(self, name, sal):
self._name=name # protected attribute
self._salary=sal # protected attribute
empl = employee("Nelu", 8000)
print(empl.name + " have " + str(empl.salary))
DEFINIREA ATRIBUTELOR PRIVATE
• Simbolul dublu de subliniere, __ prefixat unei variabile o va face privată. Ea nu poate fi accesată din afara
clasei
• Orice încercare de a face acest lucru va avea ca rezultat o eroare de tip AttributeError
• Exemplu definire:
class employee:
def __init__(self, name, sal):
self.__name=name # private attribute
self.__salary=sal # private attribute
empl = employee("Nelu", 8000)
print(empl.name + " have " + str(empl.salary))
CREAREA OBIECTELOR ÎN PYTHON
• Obiectul este un exemplar al clasei. El reprezintă un set de date (variabile) și metode (funcții) ce pot acționa
asupra datelor obiectului
• Atunci când se definește clasa – se definește doar descrierea obiectelor, nealocându-se nicicum spațiu de
memorie. La definirea obiectului – acestuia i se alocă spațiu de memorie
• Un exemplu de creare al unui exemplar ce aparține clasei Butterfly ar putea fi:
object1 = Butterfly()
print(object1.name)
METODELE OBIECTELOR
• Obiectele, pe lângă caracteristici, posedă și metode. Metodele sunt definite în clase
• Metodele sunt funcții, ce aparțin obiectelor și care definesc comportamentul acestora
• Exemplu:
class Butterfly:
def __init__(self, name, color):
self.name = name
self.color = color
def fly(self):
pass
obj = Butterfly("Skipper", "yellow")
obj.fly()
print("Done")
print(obj.name, obj.color, sep="-->")
CONSTRUCTORI ÎN PYTHON
• Funcțiile definite într-o clasă, care încep cu două liniuțe de subliniere (__), sunt numite funcții speciale,
deoarece au o destinație mai deosebită
• Un interes aparte îl prezintă funcția __init __(). Această funcție specială se apelează ori de câte ori este
creat un exemplar al unei clase
• Acest tip de funcție, în programarea OO, este numită constructor – această noțiune rar când se întâlnește
în Python. De obicei, această funcție-constructor este utilizată pentru a fi inițializate toate variabilele clasei
FUNCȚIA / METODA __INIT__()
• __init __() este o funcție predefinită – toate clasele trebuie să posede funcția cu denumirea __init __(),
funcție care se îndeplinește mereu la inițializarea clasei, o singură dată
• Metoda __init__ se apelează o singură dată, și nu poate fi apelată în mod repetat în interiorul programului
• Funcția __init __() se apelează automat de fiecare dată când clasa este utilizată pentru a crea un nou obiect
• !!! Utilizați funcția __init __() pentru atribuirea valorilor variabilelor clasei de obiecte sau ale altor operații,
necesare a fi îndeplinite în momentul creării obiectelor
PARAMETRUL SELF
• Clasele au nevoie de un mod de a se referi la ele însele. Acesta este modul de comunicare între instanțe
• Cuvântul-rezervat self este un mod de a descrie un obiect
• Parametrul self reprezintă o referință la exemplarul curent al clasei, și este utilizat pentru a accesa
variabilele clasei
• Nu este obligatoriu să fie numit self – poate fi numit oricum, dar el trebuie să fie primul parametru în orice
funcție a clasei
ȘTERGEREA ATRIBUTELOR ȘI OBIECTELOR
• Orice atribut al unui obiect poate fi lichidat în orice moment cu ajutorul instrucțiunii del. De asemenea, cu ajutorul instrucțiunii del, poate fi lichidat și
un anumit obiect. Exemplu:
class Butterfly:
'''My first class'''
def __init__(self, name, color):
self.name = name
self.color = color
def fly(self):
pass
obj = Butterfly("Skipper", "yellow")
print(obj.name)
del obj.name
del obj
print(obj.name) # se va genera o eroare
DESTRUCTORI
• Este cunoscut faptul că un constructor este apelat atunci când se instanțiază clasa, dar
atunci când un obiect este lichidat - se va apela o metodă specială numită destructor
• În Python destructorul se implementează prin intermediul metodei speciale __del__()
• Trebuie remarcat faptul că metoda nu va fi apelată dacă la obiect există măcar o referință
• Dar deoarece interpretatorul oricum își va ”bate capul” referitor la distrugerea obiectelor,
utilizarea destructorului, de cele mai multe ori, nu are sens
PRINCIPIILE POO DE BAZĂ, ÎN PYTHON
GETTER-E ȘI SETTER-E ÎN PYTHON
• Acest tip de metode în POO, reprezintă modalități de obținere și de modificare ale
datelor
• Conform principiului încapsulării, variabilele clasei se definesc ca fiind private, cu
scopul ”ascunderii” și securizării accesului la ele
• Dacă am fi scris codul Python pentru definirea clasei, conform recomandărilor
existente în Java sau PHP, am fi definit atributele: name și color – ca fiind
inaccesibile / private.
CUM SOLUȚIONEAZĂ PRINCIPIUL ÎNCAPSULĂRII
PYTHON?
• Python propune o altă soluție pentru această problemă. Soluția se numește properties – ceea ce semnificativ ușurează
procesul de codificare în cadrul metodei OO
• În Python, property() – este o funcție predefinită, care creează și returnează obiectul proprietății
• Sintaxa acestei funcții este:
def subst(a,b):
print("a-b = ", a-b)
def summ(x,y):
print("x+y = ", x+y)
subst(88, 77)
summ(88, 77)
• Le vom completa astfel încât, înainte de apelul lor să apară afișat textul “Run function”, iar la ieșirea din funcție – “Stop function”
• Acest lucru poate fi realizat prin 2 metode
1. Prima soluție ar fi să se adauge textele menționate la începutul și la sfârșitul fiecărei funcții – dar acest lucru nu este foarte comod deoarece dacă nu vom mai dori
afișarea acestor mesaje – va trebui să modificăm iar corpul funcțiilor. Dar dacă aceste funcții au fost scrise de altcineva sau dacă fac parte dintr-un proiect comun la
care participă mai mulți developeri? – nu va fi atât de simplu de realizat...
2. Cea de-a doua soluție ar fi utilizarea posibilităților funcțiilor din Python…
DECORATORII METODELOR ÎN PYTHON
• Metodele claselor pot fi definite și prin intermediul unui decorator
• Funcțiile și metodele sunt numite apelabile, deoarece pot fi apelate
• De fapt, orice obiect care implementează metoda specială __call __() se numește apelabil
• Python are și decoratori predefiniți
• În acest context, se poate utiliza simbolul @ împreună cu numele funcției-decorator, și
toată această construcție se amplasează deasupra definirii funcției, care urmează a fi
decorată
PRINCIPIUL MOȘTENIRII
• Moștenirea reprezintă o posibilitate de creare a unei noi clase, utilizând detalii ale unei alte clase, deja definite, fără a o modifica pe ultima
• Clasa nou formată va fi o clasă derivată din clasa părinte. Adică, se creează o clasă-urmaș
• De asemenea, clasa existentă deja, reprezintă o clasă de bază, numită și clasă-părinte
• În Python există funcția standard, numită și ”superfuncție” - super(), care returnează un proxiobiect, ce permite referirea la clasa părinte
• O superfuncție în Python poate fi utilizată pentru a obține acces la metodele moștenite din clasa părinte (în locul funcției ”super()” poate fi utilizat numele
clasei-părinte)
• Sintaxa:
class ParentClass():
def __init__(self): pass
class SubClass(ParentClass):
def __init__(self):
super()
REDEFINIREA METODELOR ÎN PYTHON
MasinaHibrida are un constructor propriu (__init__), care inițializează atât atributele sale
specifice, cât și cele moștenite de la clasele părinte.
Metodele afiseaza_informatii_electrica și afiseaza_informatii sunt disponibile în
MasinaHibrida datorită moștenirii.
Se adaugă o metodă nouă, afiseaza_informatii_hibrida, specifică pentru clasa
MasinaHibrida.
MOȘTENIREA MULTIPLĂ
• În C ++, clasa poate deriva de la câteva clase-părinte. În Python – este la
fel. Și acest proces este numit ”moștenire multiplă”
• La moștenirea multiplă, se vor moșteni toate proprietățile claselor-
părinte în clasa-urmaș
• Sintaxa moștenirii multiple este analogică celei de moștenire singulară:
class Base1:
pass
class Base2:
pass
class MultiDerived(Base1, Base2):
pass
MOȘTENIREA MULTIPLĂ
• De altfel, în Python este posibilă moștenirea proprietăților unei alte clase-urmaș,
adică a unei clase care a moștenit proprietăți de la o altă clasă. Acest tip de
moștenire se numește moștenire multiplă în câteva nivele
• În cazul moștenirii multiple, în câteva nivele, proprietățile din clasa de bază și cele
din clasa-urmaș a ei, vor fi moștenite de o altă clasă-urmaș
• Sintaxa:
class Base:
pass
class Derived1(Base):
pass
class Derived2(Derived1):
pass
PRINCIPIUL POLIMORFISMULUI
• În POO – polimorfismul este capacitatea de utilizare a unei interfețe comune pentru
câteva tipuri de date (clase)
• De exemplu, este necesară colorarea unei figuri geometrice. Există câteva variante de
figuri – dreptunghi, pătrat, cerc etc. Noi, însă, am putea utiliza aceeași metodă, pentru a
colora orice formă
• Acest concept și este polimorfismul
EXEMPLU
class Butterfly: # common interface
def fly(self): def who_can_flying(insect): who_can_flying()