Python: variables estàtiques o de classe

De Cacauet Wiki
Salta a la navegació Salta a la cerca

Una variables de classe o "estàtica" és una variable comuna per totes les instàncies d'una classe.


Teoria

Els atributs o variables son:

  • D'instància: valor particular per una instància (els habituals).
  • De classe: atribut compartit per totes les instàncies.

Referències:

Aplicacions típiques:

  • Carregar en memòria elements comuns de la classe (p.ex. imatges)
  • Controlar el nombre d'instàncies creades
  • Tenir una instància única d'un objecte (singleton), p.ex. QApplication
  • ...

Podem accedir a les variables de classe de dues maneres:

<instancia>.__class__.<atribut>

o bé:

<nom_classe>.<atribut>


Comptar el nombre d'instàncies creades

Per exemple, si tenim una interfície gràfica i volem saber quants botons hem creat:

class Boto:
    total = 0
    def __init__(self):
        self.__class__.total += 1

Aquest atribut serà comú per totes les instàncies:

>>> b1 = Boto()
>>> b1.total
1
>>> b2 = Boto()
>>> print b1.total,b2.total
(2, 2)


Altres formes de fer el mateix

Del què es tracta és de que no en ens "peti" el programa perquè la variable de classe no ha estat creada. Abans l'hem creat a la pròpia definició de la classe. Ara ho farem d'altres maneres.

Utilitzant hasattr:

class Boto:
    def __init__(self):
        # ens assegurem que hem creat l'atribut "total"
        if hasattr(self.__class__, "total"):
            self.__class__.total += 1
        else:
            # si no l'hem creat, el creem ara
            self.__class__.total = 1

Utilitzant excepcions:

class Boto:
    def __init__(self):
        # intentem incrementar l'atribut "total"
        try:
            self.__class__.total += 1
        except:
            # si falla (excepció), el creem i inicialitzem a 1 (1a instància)
            self.__class__.total = 1


Comportaments inesperats

ULL, perquè posar una variable en la definició de la classe no ens assegura que sigui una variable comuna a totes.

Si em vull assegurar que estic tocant la variable de classe cal accedir-hi a través de <classe/instancia>.__class__.<attr>


Mètodes estàtics

Puc definir un mètode estàtic en un objecte mitjançant el decorator @staticmethod.

Podré accedir a les variables de classe directament sense el __class__, utilitzant el nom de la classe:

class Boto:
    total = 0
    def __init__(self):
        self.inicialitza()
        
    @staticmethod
    def inicialitza():
        Boto.total += 1