2017-01-19 17 views
0

Любая рифма или причина того, почему вызываемый вызов не может быть вызван в Python 3.5 with заявление?Почему не вызываемый вызываемый внутри Python с блоком?

class Seriously(object): 
    def __init__(self, name): 
     self.name = name 

    def __enter__(self): 
     print("Enter " + self.name) 

    def __call__(self): 
     print("Call " + self.name) 

    def __exit__(self, type, value, traceback): 
     print("Exit " + self.name) 

a = Seriously('a') 
a.__enter__() 
a() 
a.__enter__() 

with Seriously('b') as b: 
    b() 

серьезно производит

Enter a 
Call a 
Enter a 
Enter b 
Exit b 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-6-91a5d11e1b2e> in <module>() 
    18 
    19 with Seriously('b') as b: 
---> 20  b() 

TypeError: 'NoneType' object is not callable 

Что я отсутствующий в PEP 343?

ответ

4

Вы ничего не возвращаете из метода __enter__, который преобразуется компилятором python в значение None. Вы должны вернуть значение, которое должно быть связано с предложением as от __enter__.

with заявление обессахаренная в

mgr = (EXPR) 
exit = type(mgr).__exit__ 
value = type(mgr).__enter__(mgr) ### <--- usually the same as mgr.__enter__() 
exc = True 
try: 
    try: 
     VAR = value    ### <--- value returned by __enter__, VAR from with/as statement 
     BLOCK 
    except: 
     exc = False 
     if not exit(mgr, *sys.exc_info()): 
       raise 
finally: 
    if exc: 
     exit(mgr, None, None, None) 

(от PEP вы связаны в этом вопросе).

+0

'return self' в конце __call__ сделал. Принят когда-то возможность, спасибо. –

0

Метод __enter__ может возвращать объект (self) явно, конструктор уже был вызван до __enter__. Вы можете просто передать объект или изменить его или вернуть другой объект.

Метод __exit__ получает четыре аргумента, self, за которыми следует тип исключения, значение и объект трассировки - то же, что и возвращаемый sys.exc_info(). Если исключение не было, то тремя параметрами исключений являются все None.

Если __exit__ возвращает True, это означает, что исключение обрабатывается и не распространяется. Возвращаемое значение False указывает, что не было исключения.

+1

Нельзя возвращать 'self' из' __enter__'. Это зависит от требования –

+0

@MoinuddinQuadri: да, я должен был сказать * мог * вместо * should *. Я говорю: «Вы можете просто передать объект или изменить его или вернуть другой объект». – cdarke

+0

Я думаю, что * should * был в порядке, поскольку он является обязательным (не является «ничем не нужен с' with'), чтобы вернуть какой-то объект, но не стоит упоминать о 'self' в самом начале этого ответа , Вы можете упомянуть о 'self' в качестве предложения позже в ответе, поскольку он соответствует требованиям OP. PS: Просто моя мысль :) –