Python - atrybut instancji, atrybut klasy

Python jest dziwnym językiem, językiem silnie zależnym od konwencji. Chociaż wiedziałem, że dużo w tym języku zależy od konwencji, mocno mnie zaskoczyło to, jak bardzo konwencja wpływa na programy w pythonie. Bloki kodu wydzielone poprzez wcięcia to banał.

Poruszyło mnie dość mocno jedna rzecz, deklaracja atrybutów klasy. Zanim zacząłem pisać pierwszy program w pythonie, trochę poczytałem, więc mniej więcej wiedziałem, że tworząc klasę, można mieć atrybuty klasy (statyczne), jak i instancji, do których odwołać można się w następujący sposób:

class Klasa(object):

    def __init__(self):
        self.someMethod()

    def someMethod(self):
        //atrybut instancji
        self.atrybut
        //atrybut klasy
        self.__class__.atrybut

Oczywiście, nie ma żadnego słowa kluczowego, który by zasugerował, że atrybut jest taki, lub taki. Ja, jak to mam w zwyczaju, atrybuty deklaruję zawsze w klasie, a następnie do nich się odwołuję:

class Klasa(object):
    atrybut = []

    def __init__(self):
        self.someMethod()

    def someMethod(self):
        //atrybut instancji
        self.atrybut
        //atrybut klasy
        self.__class__.atrybut

Z takim podejściem jest jeden kłopot. Załóżmy teraz takie odwołanie do atrybutu w metodzie:

class Klasa(object):
    atrybut = []

    def __init__(self):
        self.someMethod()

    def someMethod(self):
        //atrybut instancji (?)
        self.atrybut.append('string')

Python ma dość nietypowe podejście do atrybutów klasy (statycznych). Po pierwsze, deklaracja atrybutów w ciele klasy jest przede wszystkim statyczna - atrybuty klasy. I moje przyzwyczajenie nie wydaje się być złe. Pozwala na deklarację jakichś wartości domyślnych dla obiektów. Co się natomiast dzieje w metodzie *someMethod*? Wszelkie przewodniki twierdzą, że jest to odwołanie do atrybutu klasy, jednak w tym wypadku, Łańcuch znaków 'string' zostaje dodany do atrybutu statycznego. Dlaczego, w końcu odwołujemy się teoretycznie do atrybutu instancji?

Jak się okazuje, atrybuty klas w pythonie działają na zasadzie słowników (coś jak tablica w php, posiada klucze i wartości). W momencie, gdy atrybutu nie ma w słowniku instancji, jest szukany w słowniku klasy, a jeśli tam go nie ma, w słowniku klasy, którą nasza rozszerza. W powyższym przykładzie zadeklarowany jest atrybut klasy, a w metodzie *someMethod*, odwołanie zostaje skierowane do atrybutu klasy właśnie. Jak więc dodać atrybut do słownika trybutów instancji? Tylko poprzez wcześniejszą inicjację atrybutu:

class Klasa(object):
    atrybut = []

    def __init__(self):
        // odwołanie do atrybutu klasy
        self.someMethod()
        // inicjacja atrybutu instancji
        self.atrybut = []
        // odwołanie do atrybutu instancji
        self.someMethod()

    def someMethod(self):
        //atrybut instancji (?)
        self.atrybut.append('string')

Zanim się w tym zorientowałem, doprowadziłem do małego wycieku pamięci ;-).

Więcej do poczytania (po angielsku) na ten temat można znaleźć w tym linku:

http://docs.python.org/tutorial/classes.html#python-scopes-and-namespaces

Komentarze

Comments powered by Disqus