Члены Класса 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
, но имеют свои собственные отличительные selfvar
s. Вот простой, конкретный пример того, как это работает:
>>> 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}
детали специальный атрибут класс