gpt4 book ai didi

有条件地使用上下文管理器的 Pythonic 方式

转载 作者:行者123 更新时间:2023-12-02 03:20:28 29 4
gpt4 key购买 nike

这是我认为必须经常出现的问题,但我一直无法找到一个好的解决方案。假设我有一个函数,它可以作为参数传递一个开放资源(如文件或数据库连接对象),或者需要自己创建一个。如果函数需要自己打开文件,最佳实践通常是这样的:

with open(myfile) as fh:
# do stuff with open file handle...

确保文件在 with 时始终关闭 block 退出。但是,如果在函数中传递了现有文件句柄,则可能不应该自行关闭它。

考虑以下函数,该函数将打开的文件对象或给出文件路径的字符串作为其参数。如果它传递了一个文件路径,它可能应该像上面那样写。否则 with语句应省略。这导致重复的代码:

def foo(f):
if isinstance(f, basestring):
# Path to file, need to open
with open(f) as fh:
# do stuff with fh...
else:
# Assume open file
fh = f
# do the same stuff...

这当然可以通过定义一个辅助函数并在两个地方调用它来避免,但这似乎不优雅。我想到的更好的方法是定义一个包装对象的上下文管理器类,如下所示:

class ContextWrapper(object):
def __init__(self, wrapped):
self.wrapped = wrapped
def __enter__(self):
return self.wrapped
def __exit__(self, *args):
pass

def foo(f):
if isinstance(f, basestring):
cm = open(f)
else:
cm = ContextWrapper(f)

with cm as fh:
# do stuff with fh...

这可行,但除非有一个内置对象可以做到这一点(我认为没有),否则我要么必须将该对象复制粘贴到任何地方,要么总是必须导入我的自定义实用程序模块。我觉得有一种更简单的方法可以做到这一点,但我错过了。

最佳答案

但是,我更喜欢,我不知道它是多么pythonic,但它很简单

def foo(f):
if isinstance(f, basestring):
f = open(f)
try:
# do the stuff
finally:
f.close()

使用 singledispatch 可以更好地解决问题从python 3.4
from functools import singledispatch

@singledispatch
def foo(fd):
with fd as f:
# do stuff
print('file')

@foo.register(str)
def _(arg):
print('string')
f = open(arg)
foo(f)


foo('/tmp/file1') # at first calls registered func and then foo
foo(open('/tmp/file2', 'r')) # calls foo

关于有条件地使用上下文管理器的 Pythonic 方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33928590/

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