2017-01-19 41 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的返回结果。您应该返回__enter__as子句所绑定的值。

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

在__call__结束处'return self'做到了。会接受一次,谢谢。 –

0

__enter__方法可以显式返回对象(self),构造函数已在__enter__之前被调用。你可以通过或改变它或返回一个不同的对象。

__exit__方法获取四个参数self,后跟一个异常类型,值和一个跟踪对象 - 与sys.exc_info()返回的值相同。如果没有例外,则三个例外参数都是None

如果__exit__返回True这表示异常已处理并且不会传播。返回值False表示没有异常。

+1

这不是从'__enter__'返回'self'的任务。这取决于要求 –

+0

@MoinuddinQuadri:是的,我应该说*可以*而不是*应该*。我说“你可以通过或改变它或返回一个不同的对象”。 – cdarke

+0

我认为*应该*是很好的,因为它是强制性的(不是吗?没有任何用'with')返回一些对象,但它不值得在这个答案的开头提到'self' 。您可以在答案的后面提及'self'作为建议,因为它符合OP的要求。 PS:只是我的想法:) –

相关问题