为什么 callable 在 Python with 块中不可调用?

Why isn't a callable callable within a Python with block?

关于为什么在 Python 3.5 with 语句中可调用不可调用的任何押韵或原因?

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 中缺少什么?

您不return __enter__ 方法中的任何内容,python 编译器会将其翻译成None 的return。您应该 return 值受 __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)。

__enter__ 方法可以 return 显式对象 (self),构造函数在 __enter__ 之前已经被调用。您可以只传递对象或改变它或 return 一个不同的对象。

__exit__ 方法有四个参数,self,后跟一个异常类型、值和一个回溯对象——与 returned by sys.exc_info() 相同.如果一直没有异常,那么三个异常参数都是None.

If __exit__ returns True 这表明异常已被处理并且未被传播。 return 值为 False 表示没有异常。