我有以下代码:

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

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

推荐答案

__enter__方法应该返回上下文对象.with ... as ...使用返回值__enter__来确定要给您的对象.因为你的__enter__不返回任何东西,它隐式地返回None,所以test就是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__返回True,这表示错误已被处理(本质上,__exit__的行为类似于except块),因此代码在第一个with块之后继续,因为您告诉Python一切正常.

考虑

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

您也可以考虑不要从__exit__返回True,除非您真正打算无条件地 suppress 块中的all个错误(并且完全理解 suppress 其他程序员错误的后果,以及KeyboardInterrupt, StopIteration,以及各种系统信号).

Python-3.x相关问答推荐

如何计算累积几何平均数?

我无法直接在 VSCode 中运行该程序,但可以使用 VScode 中的终端运行它

为什么 get_form 方法中小部件的更改没有反映 Django 管理站点中的更改

找到在指定列的另一个分组中存在重复的行.

Pytest顺序测试A,然后测试B,然后再测试A

如何在 Telethon 中向机器人发送发送表情符号

python 3.10.5 中可能存在的错误. id 函数工作不明确

pip 找不到最新的软件包版本

每个数据行中每个数据帧值的总和

Tkinter IntVar 返回 PY_VAR0 而不是值

ValueError:找不到子字符串,我做错了什么?

Python:如何在三个列表中找到共同值

PySpark python 问题:Py4JJavaError: An error occurred while calling o48.showString

sys.stdin.readline() 和 input():读取输入行时哪个更快,为什么?

无 Python 错误/错误?

混合全局/参数和名为top的函数的奇怪python行为

如何使用 Python 订阅 Websocket API 通道?

如何从 Python 3 导入 FileNotFoundError?

python asyncio add_done_callback 与 async def

如何从 seaborn / matplotlib 图中删除或隐藏 x 轴标签