首页 > 解决方案 > 在“with”语句中调用构造函数

问题描述

我有以下代码:

class Test:

    def __init__(self, name):
        self.name = name

    def __enter__(self):
        print(f'entering {self.name}')

    def __exit__(self, exctype, excinst, exctb) -> bool:
        print(f'exiting {self.name}')
        return True

with Test('first') as test:
    print(f'in {test.name}')

test = Test('second')
with test:
    print(f'in {test.name}')

运行它会产生以下输出:

entering first
exiting first
entering second
in second
exiting second

但我预计它会产生:

entering first
in first
exiting first
entering second
in second
exiting second

为什么不调用我的第一个示例中的代码?

标签: pythonpython-3.xclasswith-statement

解决方案


__enter__方法应返回上下文对象。with ... as ...使用的返回值__enter__来确定给你什么对象。由于您__enter__没有返回任何内容,因此它隐式返回Nonetest因此None.

with Test('first') as test:
    print(f'in {test.name}')

test = Test('second')
with test:
    print(f'in {test.name}')

也没有test。然后test.name是错误。该错误被引发,因此Test('first').__exit__被调用。__exit__return True,这表明错误已被处理(本质上,你__exit__的行为就像一个except块),所以代码在第一个with块之后继续,因为你告诉 Python 一切都很好。

考虑

def __enter__(self):
    print(f'entering {self.name}')
    return self

你也可以考虑不返回True__exit__除非你真的打算无条件地抑制块中的所有错误(并完全理解抑制其他程序员的错误的后果,以及KeyboardInterrupt,StopIteration和各种系统信号)


推荐阅读