Где определено, что менеджер контекста with вместе с RLock() неявно вызывает метод lock.acquire()? Как изучающим Python понимать подобное самим?
Изучаю Python. Тщательно, с интересом. Долго пытался понять, как же работает пример с сочетанием типа with RLock() без вызова потом в тексте необходимых методов lock.acquire() и lock.release(). В описаниях RLock или with на docs-python.ru/ указаний на это не увидел. В конце концов нагуглил, что "Оператор with в этом случае вызывает lock.acquire() при входе и lock.release() при выходе." (https://digitology.tech/posts/kontekstnye-menedzhery-v-python/) А как изучающие Phyton это должены понять сами (своими мозгами)? Из чего это следует? (Хорошо, если бы ответ затронул и потенциально схожие проблемы)
Пример кода:
class Example1:
def __init__(self):
self.lock = RLock()
def example_of_method (self):
with self.lock:
print ('lock.acquire() was just called somehow')
Ответы (2 шт):
Это описано в документации. В разделе про RLock последний абзац:
Reentrant locks also support the context management protocol.
А по ссылке это описано подробно и с примером:
All of the objects provided by this module that have acquire() and release() methods can be used as context managers for a with statement. The acquire() method will be called when the block is entered, and release() will be called when the block is exited. Hence, the following snippet:
with some_lock: # do something...is equivalent to:
some_lock.acquire() try: # do something... finally: some_lock.release()
Ну, ещё это можно понять чисто по логике. При использовании контекстного менеджера with при заходе в блок вызывается метод __enter__, при выходе __exit__. А дальше нужно смотреть - что именно вызывается в этих методах. Можно либо посмотреть исходники библиотеки и увидеть, что там как-раз и вызываются acquire и release, либо можно через dir() посмотреть, какие есть публичные методы у self.lock и увидеть, что их собственно всего два этих метода и один из них должен вызываться при входе в блок, а другой при выходе. Без вариантов в данном случае, у объекта, создаваемого через RLock(), просто нет никаких других публичных методов для вызова.