Członkowie Klasy Python

Dopiero uczę się Pythona i pochodzę z języka C, więc proszę dać mi znać, jeśli będę miał jakieś zamieszanie / pomieszanie między obydwoma.

Załóżmy, że mam następującą klasę:

class Node(object):
    def __init__(self, element):
        self.element = element
        self.left = self.right = None

    @classmethod
    def tree(cls, element, left, right):
        node = cls(element)
        node.left = left
        node.right = right
        return node

Jest to klasa o nazwie Node, która przeciąża konstruktor, aby móc obsługiwać różne argumenty w razie potrzeby.

Jaka jest różnica między definiowaniem self.element tylko w __init__ (Jak pokazano powyżej), a nie wykonywaniem następujących czynności:

class Node(object):
    element, left, right = None
    def __init__(self, element):
        self.element = element
        self.left = self.right = None

Isn ' t self.element in __init__ the same as the class ' S element variable defined? Czy to nie nadpisałoby element z None na element wartość przekazaną do __init__?

Author: smci, 2012-09-13

6 answers

Jeden jest atrybutem klasy, podczas gdy drugi jest atrybutem instancji. Są różne, ale są ze sobą blisko spokrewnione w taki sposób, że czasami wyglądają tak samo.

Ma to związek ze sposobem, w jaki python wyszukuje atrybuty. Jest hierarchia. W prostych przypadkach może to wyglądać tak:

instance -> Subclass -> Superclass -> object (built-in type)

Gdy szukasz atrybutu na instance w ten sposób...

`instance.val`

...tak naprawdę to pierwszy , Python szuka val w sama instancja. Następnie, jeśli nie znajdzie val, szuka w swojej klasie, Subclass. Następnie, jeśli nie znajdzie val tam, zagląda do rodzica Subclass, Superclass. Oznacza to, że kiedy to robisz...

>>> class Foo():
    foovar = 10  
    def __init__(self, val):
        self.selfvar = val

...wszystkie instancje Foo podziel się foovar, ale mają swoje własne odrębne selfvar s. Oto prosty, konkretny przykład tego, jak to działa: {]}

>>> f = Foo(5)
>>> f.foovar
10
>>> Foo.foovar
10

Jeśli nie dotykamy foovar, to jest to samo dla f i Foo. Ale jeśli zmienimy f.foovar...

>>> f.foovar = 5
>>> f.foovar
5
>>> Foo.foovar
10

...dodajemy atrybut instancji, który skutecznie maskuje wartość Foo.foovar. Jeśli zmienimy Foo.foovar bezpośrednio, nie wpłynie to na naszą instancję foo:

>>> Foo.foovar = 7
>>> f.foovar
5

Ale to wpływa na nową instancjęfoo:

>>> Foo(5).foovar
7

Należy również pamiętać, że zmienne obiekty dodają kolejną warstwę indrection (jak przypomniał mi mgilson). Tutaj f.foovar odnosi się do tego samego obiektu co Foo.foovar, więc kiedy zmienisz obiekt, zmiany są propagowane w hierarchii:

>>> Foo.foovar = [1]
>>> f = Foo(5)
>>> f.foovar[0] = 99
>>> Foo.foovar
[99]
 62
Author: senderle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-13 16:00:27

W Pythonie możliwe jest posiadanie zmiennych klasowych i zmiennych instancji o tej samej nazwie. Znajdują się one oddzielnie w pamięci i są dostępne zupełnie inaczej.

W kodzie:

class Node(object):
    element, left, right = None
    def __init__(self, element):
        self.element = element
        self.left = self.right = None

Pierwszy zbiór zmiennych (poza funkcją __init__) nazywa się zmiennymi klasy. Następnie można uzyskać do nich dostęp za pomocą Node.element, itd. Są one równoważne ze statycznymi zmiennymi składowymi w C++ i są współdzielone przez wszystkie instancje klasy.

Drugi zestaw zmienne (wewnątrz funkcji __init__) nazywane są zmiennymi instancji. Są one dostępne przez obiekt self, np. self.element, lub przez nazwę instancji, np. myNode.element poza klasą.

Ważne jest, aby pamiętać, że musisz użyć formularza self.variable lub Node.variable, aby uzyskać dostęp do jednej z nich z poziomu funkcji Członkowskich. Po prostu dostęp do {[9] } będzie próbował uzyskać dostęp do zmiennej lokalnej o nazwie variable.

 10
Author: Lee Netherton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-13 15:42:46

Self.element wewnątrz konstruktora jest zmienną instancyjną (jeśli obiekt węzła modyfikuje swoją wartość, zmienia się tylko dla tego obiektu), gdzie ten w drugiej wersji jest zmienną klasy (więc jeśli jeden obiekt węzła modyfikuje swoją wartość, zmieni się dla wszystkich obiektów węzła).

Analogia w C++ byłaby nie-statyczna względem statycznych zmiennych członkowskich w twojej klasie.

 2
Author: Borgleader,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-13 15:29:03

Self.element w init jest zmienną instancyjną, można ją uzyskać / ustawić w dowolnej innej funkcji członkowskiej, wpisując self.element. element zadeklarowany w klasie jest zmienną klasy, można ją uzyskać / ustawić wpisując Node.element.

 0
Author: waitingkuo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-13 15:35:25

Ważną częścią jest argument self do __init__. W rzeczywistości, wdowolnej metodzie instancji , będzie to pierwszy argument. W Pythonie dostęp do instancji jest możliwy tylko podczas wywoływania metod i jest on pokazywany jawnie z argumentem self.

Kiedy jesteś wewnątrz definicji class, nie masz jeszcze żadnych instancji, więc tak naprawdę modyfikujesz samą klasę. Tak więc, jeśli zdefiniujesz atrybuty na poziomie klasy, to naprawdę stają się atrybutami klasy, a nie instancją.

Porównując go do C (++), można prawdopodobnie powiedzieć, że "klasy" w tych językach są w zasadzie schematami dla obiektów, które reprezentują. "Obiekty te posiadają atrybuty foo i bar, a ponadto następujące metody."W Pythonie, jednak klasy są same w sobie obiektami, a ich główną siłą jest to, że mogą tworzyć kopie (instancje) samych siebie, które również korzystają z metod klasy. Więc to bardziej podobnie jak " będziesz miał foo i bar jako atrybuty klasy, a ponadto następującą metodę, której użyjesz do tworzenia instancji."

Więc zamiast planu, to bardziej krok po kroku jak to zrobić.

 0
Author: voithos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-13 15:41:09

Kiedy próbujesz uzyskać dostęp do zmiennej z klasą, wygląda ona tylko

cls.__dict__

Ale gdy próbujesz uzyskać dostęp do zmiennej z instancją, wygląda ona najpierw

self.__dict__ 

If find then return or if can ' t find then it also looks in

cls.__dict__

Tutaj cls jest klasą

class Test:
    temp_1=10
    temp_2=20

    def __init__(self):
        self.test_1=10
        self.test_2=20

    @classmethod
    def c_test(cls):
        pass

    def t_method(self):
        pass


print Test.__dict__
print Test().__dict__

Wyjście :

{'c_test': <classmethod object at 0x7fede8f35a60>, '__module__': '__main__', 't_method': <function t_method at 0x7fede8f336e0>, 'temp_1': 10, '__doc__': None, '__init__': <function __init__ at 0x7fede8f335f0>, 'temp_2': 20}

{'test_2': 20, 'test_1': 10}

Dla detali class special attribute

 0
Author: Kallz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-30 07:36:54