gpt4 book ai didi

python - 上下文管理器作为类还是函数?

转载 作者:行者123 更新时间:2023-12-01 02:07:04 25 4
gpt4 key购买 nike

我最近一直在研究 Python 的 contextmanager(更具体地说,Python 3 的 contextlib 或其向后移植的 contextlib2),我想知道将它们编写为类与函数相比有何优点/缺点?

它们似乎都以相同的方式运行并以相同的方式处理异常。有很多很酷的实用程序,例如 ExitStack(),但这些实用程序似乎可以在编写为类或函数的上下文管理器中实现。因此,我正在努力寻找一个很好的理由来解释为什么人们想要将上下文管理器详细地编写为一个类,而它们可以被编写为一个函数并且只需使用 contextmanager 装饰器即可。

这是我编写的一个简单示例,用于展示两者都在做同样的事情:

# !/usr/bin/python -u
# encoding: utf-8

from contextlib import contextmanager

# Function-based
@contextmanager
def func_custom_open(filename, mode):
try:
f = open(filename, mode)
yield f
except Exception as e:
print(e)
finally:
f.close()

# Class-based
class class_custom_open(object):

def __init__(self, filename, mode):
self.f = open(filename, mode)

def __enter__(self):
return self.f

def __exit__(self, type, value, traceback):
self.f.close()


if __name__ == '__main__':

# Function-based
with func_custom_open('holafile_func.txt', 'w') as func_f:
func_f.write('hola func!')

# Class-based
with class_custom_open('holafile_class.txt', 'w') as class_f:
class_f.write('hola class!')

最佳答案

如果你不需要使用语法的“详细”类,你就不需要它,就这么简单。

两者都存在的原因是使用类的方式是上下文管理器在该语言中工作的实际方式。任何在其类中具有 __enter__ 和 __exit__ 方法的对象都可以用作上下文管理器。

使用@contextmanager并允许将上下文管理器声明为函数的方式只是Python标准库中的一种实用工具。装饰器生成的是一个具有这两种方法的对象。

将上下文管理器编写为类可能会更紧凑的一种情况是,用作上下文管理器的对象也是您控制下的类,然后您可以更好地集成运行 __enter____exit__ 在其生命周期中。例如,看到可用作装饰器或上下文管理器的对象并不罕见(我想到的是unittest.mock.patch)。对于用户来说,这听起来只是“魔法”,但实现非常清晰且定义良好:在此类对象的类中,它充当上下文管理器的逻辑位于 __enter__/__exit__,实现装饰器行为的逻辑位于__call__方法上。

关于python - 上下文管理器作为类还是函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48957645/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com