Zanurkuj w Pythonie/Atrybuty klas

Atrybuty klas

edytuj

Wiemy już, co to są atrybuty, które są częścią konkretnych obiektów. W Pythonie możemy tworzyć też atrybuty klas, czyli zmienne należące do samej klasy (a nie do instancji tej klasy).

Przykład. Atrybuty klas
class MP3FileInfo(FileInfo):
    u"przechowuje znaczniki ID3v1.0 MP3"
    tagDataMap = {u"tytuł"    : (  3,  33, stripnulls),
                  "artysta"   : ( 33,  63, stripnulls),
                  "album"     : ( 63,  93, stripnulls),
                  "rok"       : ( 93,  97, stripnulls),
                  "komentarz" : ( 97, 126, stripnulls),
                  "gatunek"   : (127, 128, ord)} 

>>> import fileinfo
>>> fileinfo.MP3FileInfo                     #(1)
<class 'fileinfo.MP3FileInfo'>
>>> fileinfo.MP3FileInfo.tagDataMap          #(2)
{'album': (63, 93, <function stripnulls at 0xb7c000d4>),
'rok': (93, 97, <function stripnulls at 0xb7c000d4>),
'komentarz': (97, 126, <function stripnulls at 0xb7c000d4>),
u'tytu\u0142': (3, 33, <function stripnulls at 0xb7c000d4>),
'artysta': (33, 63, <function stripnulls at 0xb7c000d4>),
'gatunek': (127, 128, <built-in function ord>)}
>>> m = fileinfo.MP3FileInfo()               #(3)
>>> m.tagDataMap
{'album': (63, 93, <function stripnulls at 0xb7c000d4>),
'rok': (93, 97, <function stripnulls at 0xb7c000d4>),
'komentarz': (97, 126, <function stripnulls at 0xb7c000d4>),
u'tytu\u0142': (3, 33, <function stripnulls at 0xb7c000d4>),
'artysta': (33, 63, <function stripnulls at 0xb7c000d4>),
'gatunek': (127, 128, <built-in function ord>)}
  1. MP3FileInfo jest klasą, nie jest instancją klasy.
  2. tagDataMap jest atrybutem klasy i jest dostępny już przed stworzeniem jakiegokolwiek obiektu danej klasy.
  3. Atrybuty klas są dostępne na dwa sposoby: poprzez bezpośrednie odwołanie do klasy lub poprzez jakąkolwiek instancję tej klasy.

Atrybuty klas mogą być używane jako stałe tych klas (w takim celu korzystamy z nich w klasie MP3FileInfo), ale tak naprawdę nie są stałe. Można je zmieniać.

Przykład. Modyfikowanie atrybutów klas
>>> class counter(object):
 ...     count = 0                       #(1)
 ...     def __init__(self):
 ...         self.__class__.count += 1   #(2)
 ...     
 >>> counter
 <class __main__.counter>
 >>> counter.count                       #(3)
 0
 >>> c = counter()
 >>> c.count                             #(4)
 1
 >>> counter.count
 1
 >>> d = counter()                       #(5)
 >>> d.count
 2
 >>> c.count
 2
 >>> counter.count
 2
  1. count jest atrybutem klasy counter.
  2. __class__ jest wbudowanym atrybutem każdego obiektu. Jest to referencja do klasy, której obiektem jest self (w tym wypadku do klasy counter).
  3. Ponieważ count jest atrybutem klasy, jest dostępny poprzez bezpośrednie odwołanie do klasy, przed stworzeniem jakiegokolwiek obiektu.
  4. Kiedy tworzymy instancję tej klasy, automatycznie zostanie wykonana metoda __init__, która zwiększa atrybut tej klasy o nazwie count o 1. Operacja ta wpływa na klasę samą w sobie, a nie tylko na dopiero co stworzony obiekt.
  5. Stworzenie drugiego obiektu ponownie zwiększy atrybut count. Zauważmy, że atrybuty klas są wspólne dla klasy i wszystkich jej instancji.