__init__()
- это просто метод, который вызывается при инициализации объекта. В Python память объекта не фиксируется во время инициализации. Объект Python сильно отличается от объекта C ++ или Java. Объект Python можно рассматривать как более близкий к пространству имен в Python, что позволяет вам содержать в нем коллекцию членов (функций и значений). Эта коллекция может быть легко расширена в Python в любой момент времени жизни объекта. Объект не содержит этих членов сам по себе, он просто поддерживает ссылки на них.
Когда вы пишете {obj}.{name} = {some_val}
, Python проверяет, имеет ли объект атрибут {name}
. Если это так, атрибуту присваивается значение {some_val}
, в противном случае Python добавляет имя {name}
в пространство имен объекта и инициализирует его как {some_val}
. Обратите внимание, что Python не нужно создавать дополнительное пространство для name
в объекте, он просто должен отслеживать новую переменную name
, которая была введена в пространство имен (я описал, как это происходит позже) , Это связано с тем, что модель данных Python основана на именах, что отличается от языков, подобных C ++. Пространство для name
выделено в другом месте, name
- это просто ссылка на этот объект.
На самом деле вы можете увидеть, что это происходит под капотом, используя функцию dir()
. Для каждого объекта в Python, Python поддерживает атрибут __dir__
, который представляет собой список всех имен, присутствующих в области действия объекта. Это включает в себя имена переменных и имена функций.
Итак, в вашем случае, если вы позвоните dir(b)
до b.student = "John"
, вы получите следующее:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'check', 'lesson']
Обратите внимание, что это включает много более сложных методов, наряду с методами check
и lesson
, которые вы определили.
После запуска b.student = "John"
мы получим
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'check', 'lesson', 'student']
Обратите внимание, как называется student
был добавлен в пространство имен b
в конце списка.
Итак, {x}.{y}={something}
- это простой способ, которым имя y
можно добавить в пространство имен x
. Зная это, можно увидеть, что функции __init__()
не являются специальными. Они делают то же самое, просто __init__()
вызывается всякий раз, когда инициализируется объект.
Еще одна интересная вещь, которую следует отметить, это то, что все в Python является объектом (классы и функции также объекты!); так что совершенно нормально написать что-то вроде:
>>> def f():
f.ctr += 1 #f.ctr stores number of times f has been called
#do something
>>> f.ctr = 0
>>> f()
>>> f()
>>> f()
>>> f.ctr
3