Как объект создается в блоке "с"?

66
5

Я сделал следующее в интерпретаторе python (2.7.13):

>>> class test:
... def __init__(self):
... print "Object has been constructed!"
... def __enter__(self):
... print "Entering with"
... def __exit__(self, type, value, traceback):
... print "Exiting with"
...
>>>
>>> t1 = test()
Object has been constructed!
>>> print t1
<__main__.test instance at 0x7fed5383e3b0>
>>>
>>> with test() as t1:
... print "Inside 'with' block"
... print t1
...
Object has been constructed!
Entering with
Inside 'with' block
None
Exiting with

Мой вопрос: почему не делает print выводит none внутри with блоком? Кажется, что объект создается с with (по крайней мере, мы видим, что есть вызов конструктора), но t1, похоже, не существует в пространстве имен. Это нормально?

спросил(а) 2016-12-21T11:45:00+03:00 3 года, 6 месяцев назад
1
Решение
86

Он печатает None потому что __enter__ возвращает None (неявно).

Рассмотрим следующий образец:

class test:
def __init__(self):
print "Object has been constructed!"
def __enter__(self):
print "Entering with"
return 5
def __exit__(self, type, value, traceback):
print "Exiting with"

with test() as t1:
assert t1 == 5

AssertionError не поднимается, поэтому мы знаем, что t1 равно 5.

В общем случае значение, присвоенное something в with ctx_mgr as something: может быть любым, а не строго ctx_mgr. Если это должно быть ctx_mgr, with... as... конструкцией будет избыточно.

ответил(а) 2016-12-21T11:50:00+03:00 3 года, 6 месяцев назад
76

вам нужно вернуть self (или любой другой объект в зависимости от ваших потребностей) в методе менеджера контекста __enter__; результат этой функции присваивается as:

class test:
...
def __enter__(self):
print( "Entering with")
return self
...

как это работает в описанных в типах диспетчера контекста python.

ответил(а) 2016-12-21T11:50:00+03:00 3 года, 6 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема