Члены Класса Python

я только изучаю Python, и я пришел из фона C, поэтому, пожалуйста, дайте мне знать, если у меня есть путаница / путаница между обоими.

Предположим, у меня есть следующий класс:

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

это класс с именем Node, который перегружает конструктор, чтобы иметь возможность обрабатывать различные аргументы, если это необходимо.

в чем разница между определением self.element на __init__ только (как показано выше), а не делать следующий:

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

не self.element на __init__ то же, что и класс element переменной определяешь? Не просто переписать element С None до element значением, переданным в __init__?

6 ответов


один является атрибутом класса, а другой-атрибутом экземпляра. Они разные, но они тесно связаны друг с другом таким образом, что временами выглядят одинаково.

это связано с тем, как python ищет атрибуты. Есть иерархия. В простых случаях это может выглядеть так:

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

когда вы ищете атрибут на instance такой...

`instance.val`

...что на самом деле происходит, что первый, Python ищет val в самом экземпляре. Тогда, если он не найдет val, он выглядит в своем классе Subclass. Тогда, если он не найдет val вот, он смотрит в родителя Subclass, Superclass. Это означает, что когда вы делаете это...

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

...все экземпляры Foo долю foovar, но имеют свои собственные отличительные selfvars. Вот простой, конкретный пример того, как это работает:

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

если мы не трогаем foovar, это то же самое для обоих f и Foo. Но если мы изменимся f.foovar...

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

...мы добавляем атрибут экземпляра, который эффективно маскирует значение Foo.foovar. Теперь если мы изменим Foo.foovar непосредственно, это не влияет на наш foo например:

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

но это влияет на новый foo например:

>>> Foo(5).foovar
7

также имейте в виду, что изменяемые объекты добавляют еще один слой косвенности (как напомнил мне мгильсон). Вот,f.foovar относится к тому же объекту as Foo.foovar, поэтому при изменении объекта изменения распространяются вверх по иерархии:

>>> Foo.foovar = [1]
>>> f = Foo(5)
>>> f.foovar[0] = 99
>>> Foo.foovar
[99]

в Python можно иметь переменные класса и переменные экземпляра с тем же именем. Они расположены отдельно в памяти и доступны совершенно по-разному.

в коде:

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

первый набор переменных (вне __init__ function) называются переменными класса. Они могут быть впоследствии доступны с помощью Node.element, etc. Они эквивалентны статическим переменным-членам в C++ и являются общими для всех экземпляров класс.

второй набор переменных (внутри __init__ function) называются переменными экземпляра. Они обращались через


self.элемент внутри конструктора является переменной экземпляра (если объект узла изменяет свое значение, он изменяется только для этого объекта), где один во второй версии является переменной класса (поэтому, если один объект узла изменяет свое значение, он изменится для всех объектов узла).

аналогия в C++ будет нестатической по сравнению со статическими переменными-членами в вашем классе.


self.элемент в init - это переменная экземпляра, вы можете получить/установить его в любой другой функции-члена, вписав себя.элемент. элемент, объявленный в классе, является переменной класса, вы можете получить / установить его, введя Node.элемент.


важная часть - и bar атрибуты, и, кроме того, следующие методы."В Python, однако, классы являются самими объектами, и их главная сила заключается в том, что они могут создавать копии (экземпляры) самих себя, которые также случается использовать методы класса. Так что, это больше похоже на "У тебя будет foo и bar как атрибуты класса и, кроме того, следующий метод, который вы должны использовать для создания экземпляров."

Итак, вместо чертежа, это скорее пошаговое руководство.


когда вы пытаетесь получить доступ к переменной с классом, он смотрит только в

cls.__dict__

но когда вы пытаетесь получить доступ к переменной с экземпляром, она выглядит сначала

self.__dict__ 

если найти, то верните или если не можете найти, то он также смотрит в

cls.__dict__

здесь cls является классом

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__

выход:

{'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}

детали специальный атрибут класс