...в отличие от инструкции в C++, в языке Python она не является объявлением. Подобно инструкции def, инструкция class создает объект и является неявной инструкцией присваивания – когда она выполняется, создается объект класса, ссылка на который сохраняется в имени, использованном в заголовке инструкции.
Когда в области видимости создается объект класса?¶
Кроме того, как и инструкция def, инструкция class является настоящим выполняемым программным кодом – класс не существует, пока поток выполнения не достигнет инструкции class, которая определяет его (обычно при импортировании модуля, в котором она находится, но не ранее).
Здесь можно было бы импортировать какой-нибудь модуль и распечатать его атрибуты командой dir..., но сейчас я думаю о том, что понимаю, почему принято использовать instances ... но как соотносятся (взаимодействуют) пространства имен класса и пространство имен экземпляра(ов)?
...функция с именем init, если она определена, вызывается во время создания объекта экземпляра (770).¶
Так как же инструкция class порождает пространство имен?¶
А вот как. Так же как и в модулях, инструкции, вложенные в тело инструкции class, создают атрибуты класса. Когда интерпретатор достигает инструкции class (а не тогда, когда происходит вызов класса), он выполняет все инструкции в ее теле от начала и до конца.
Все присваивания, которые производятся в ходе этого процесса, создают имена в локальной области видимости класса, которые становятся атрибутами объекта класса. Благодаря этому классы напоминают модули и функции:
•• Подобно функциям, инструкции class являются локальными областями
видимости, где располагаются имена, созданные вложенными операциями
присваивания.
•• Подобно именам в модуле, имена, созданные внутри инструкции class, ста-
новятся атрибутами объекта класса.
Основное отличие классов состоит в том, что их пространства имен также составляют основу механизма наследования в языке Python, – ссылки на атрибуты, отсутствующие в классе или в объекте экземпляра, будут получены из других классов.
Все инструкции внутри инструкции class выполняются, когда выполняется сама инструкция class (а не когда позднее класс вызывается для создания экземпляра).
class SharedData:
spam = 42
>>> x = SharedData() # Создать два экземпляра
>>> y = SharedData()
>>> x.spam, y.spam # Они наследуют и совместно используют атрибут spam
#(42, 42)
>>> SharedData.spam = 99
>>> x.spam, y.spam, SharedData.spam
*Здесь мы обращаемся к объекту класса, а не к экземпляру... Оба экземпляра не находят атрибута spam в своих пространствах имен, начинаю искать (и находят) в пространстве имен родителя(ей)...
Почему я вернулся к этой "очевидной теме"? Потому, что разбирал чужой код (Scrapy doc 7.5.1 Using Item Exporters), в котором использовался метод класса: *
@classmethod
def from_crawler(cls, crawler):
pipeline = cls()
crawler.signals.connect(pipeline.spider_opened, signals.spider_opened)
crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)
return pipeline
здесь переменной pipeline присваивается имя (объекта) класса. При появлении сигнала (наступлении события) signals.spider_opened вызывается метода pipeline.spider_opened
def spider_opened(self, spider):
file = open(’%s_products.xml’ % spider.name, ’w+b’)
self.files[spider] = file
self.exporter = XmlItemExporter(file)
self.exporter.start_exporting()
При этом экземпляр класса не создается. Непривычно и надо бы понять, зачем так "мудрить"... Нет, объяснить, что там в стеке асинхронные вызовы, и неизвестно заранее сколько будет пауков работать... это я могу, ... и надо бы порассуждать на эту тему... Но об этом в другом посте...
Вот пример использование одного имени атрибута 'data' в разных пространствах имен¶
class MixedNames: # Определение класса
data = 'spam' # Присваивание атрибуту класса
def __init__(self, value): # Присваивание имени метода
self.data = value # Присваивание атрибуту экземпляра
def display(self):
print(self.data, MixedNames.data) # Атрибут экземпляра, атрибут класса
>>> x = MixedNames(1) # Создаются два объекта экземпляров,
>>> y = MixedNames(2) # каждый из которых имеет свой атрибут data
>>> x.display(); y.display() # self.data - это другие атрибуты,
# а MixedNames.data - тот же самый
Несмотря на то что операция поиска в дереве наследования позволяет отыскивать имена, мы всегда можем получить доступ к ним в любой точке дерева, обратившись непосредственно к нужному объекту
обратим внимание, что функция с именем init, если она определена, вызывается во время созда- ния объекта экземпляра, а не класса
Посты чуть ниже также могут вас заинтересовать
Комментариев нет:
Отправить комментарий