Atributele claselor și metodele statice
Atributele claselor
Pe lângă atributele obiectelor, în clase se pot defini și atribute ale claselor. Astfel de atribute sunt definite ca variabile la nivel de clasă. De exemplu:
class Person:
type = "Person"
description = "Describes a person"
print(Person.type) # Person
print(Person.description) # Describes a person
Person.type = "Class Person"
print(Person.type) # Class Person
Aici, în clasa Person, sunt definite două atribute: type, care stochează numele clasei, și description, care stochează descrierea clasei.
Pentru a accesa atributele clasei, putem folosi numele clasei, de exemplu: Person.type, și, la fel ca atributele obiectului, putem obține și modifica valorile acestora.
Astfel de atribute sunt comune pentru toate obiectele clasei:
class Person:
type = "Person"
def __init__(self, name):
self.name = name
tom = Person("Tom")
bob = Person("Bob")
print(tom.type) # Person
print(bob.type) # Person
# schimbăm atributul clasei
Person.type = "Class Person"
print(tom.type) # Class Person
print(bob.type) # Class Person
Atributele clasei pot fi utilizate în situațiile în care trebuie să definim anumite date comune pentru toate obiectele. De exemplu:
class Person:
default_name = "Undefined"
def __init__(self, name):
if name:
self.name = name
else:
self.name = Person.default_name
tom = Person("Tom")
bob = Person("")
print(tom.name) # Tom
print(bob.name) # Undefined
În acest caz, atributul default_name stochează numele implicit. Și dacă în constructor este transmis un șir de caractere gol pentru nume, atunci atributul name va primi valoarea atributului clasei default_name. Pentru a accesa atributul clasei în interiorul metodelor, putem folosi numele clasei:
self.name = Person.default_name
Atributul clasei și atributul obiectului
Este posibilă situația în care atributul clasei și atributul obiectului au același nume. Dacă în cod nu este setată o valoare pentru atributul obiectului, atunci pentru acesta poate fi folosită valoarea atributului clasei:
class Person:
name = "Undefined"
def print_name(self):
print(self.name)
tom = Person()
bob = Person()
tom.print_name() # Undefined
bob.print_name() # Undefined
bob.name = "Bob"
bob.print_name() # Bob
tom.print_n
Aici metoda print_name folosește atributul obiectului name, însă nicăieri în cod acest atribut nu este setat. Însă la nivelul clasei este definit atributul name. Prin urmare, la prima apelare a metodei print_name, în ea va fi folosită valoarea atributului clasei:
tom = Person()
bob = Person()
tom.print_name() # Undefined
bob.print_name() # Undefined
Ulterior, putem seta atributul obiectului:
bob.name = "Bob"
bob.print_name() # Bob
tom.print_name() # Undefined
În plus, al doilea obiect - tom va continua să folosească atributul clasei. Și dacă schimbăm atributul clasei, corespunzător valoarea tom.name se va schimba:
tom = Person()
bob = Person()
tom.print_name() # Undefined
bob.print_name() # Undefined
Person.name = "Some Person" # schimbăm valoarea atributului clasei
bob.name = "Bob" # setăm atributul obiectului
bob.print_name() # Bob
tom.print_name() # Some Person
Metode statice
Pe lângă metodele obișnuite, o clasă poate defini și metode statice. Aceste metode sunt precedate de anotarea @staticmethod și se referă în general la clasă. Metodele statice definesc de obicei un comportament care nu depinde de un anumit obiect:
class Person:
__type = "Person"
@staticmethod
def print_type():
print(Person.__type)
Person.print_type() # Person - apelul metodei statice prin numele clasei
tom = Person()
tom.print_type() # Person - apelul metodei statice prin numele obiectului
În acest caz, în clasa Person este definit atributul clasei __type, care stochează o valoare comună pentru întreaga clasă - numele clasei. Deoarece numele atributului este precedat de două liniuțe de subliniere, acest atribut va fi privat, ceea ce îl protejează de modificările neautorizate.
De asemenea, în clasa Person este definită metoda statică print_type, care afișează în consolă valoarea atributului __type. Acțiunea acestei metode nu depinde de un anumit obiect și se referă în general la întreaga clasă - indiferent de obiect, pe consolă va fi afișată aceeași valoare a atributului __type. De aceea, o astfel de metodă poate fi făcută statică.