Ответ 1
Диспетчер контекста может необязательно возвращать объект, который должен быть назначен идентификатору, названному as
. И это объект, возвращаемый методом __enter__
который присваивается as
, не обязательно сам менеджер контекста.
Использование в as <identifier>
помогает при создании нового объекта, например, вызов open()
, но не все контекстные менеджеры создаются только для контекста. Они могут быть повторно использованы и уже созданы, например.
Возьмите соединение с базой данных. Вы создаете соединение с базой данных только один раз, но многие адаптеры баз данных позволяют использовать соединение в качестве менеджера контекста; введите контекст и начнется транзакция, выйдите из него, и транзакция будет либо зафиксирована (при успешном завершении), либо отменена (когда есть исключение):
with db_connection:
# do something to the database
Здесь не нужно создавать новые объекты, контекст вводится с помощью db_connection.__enter__()
и снова db_connection.__exit__()
с db_connection.__exit__()
, но мы уже имеем ссылку на объект соединения.
Теперь может быть, что объект соединения создает объект курсора при вводе. Теперь имеет смысл назначить этот объект курсора локальным именем:
with db_connection as cursor:
# use cursor to make changes to the database
db_connection
все еще не db_connection
здесь, оно уже существовало раньше, и у нас уже есть ссылка на него. Но независимо от db_connection.__enter__()
что db_connection.__enter__()
теперь назначается cursor
и может использоваться оттуда.
Это то, что происходит с файловыми объектами; open()
возвращает объект файла и fileobject.__enter__()
возвращает сам файл объект, так что вы можете использовать open()
вызов в with
выражением и присвоить ссылку на вновь созданный объект в одном шаге, а не два. Без этого небольшого трюка вам придется использовать:
f = open('myfile.txt')
with f:
# use 'f' in the block
Применение всего этого к вашему примеру шейдера; у вас уже есть ссылка на self.shader
. Вполне вероятно, что self.shader.__enter__()
снова возвращает ссылку на self.shader
, но поскольку у вас уже есть идеальная справочная система, зачем создавать для self.shader
новую локальную?