我认为这是一个经常出现的问题,但我还没有找到一个好的解决方案。假设我有一个函数,它可能会将一个打开的资源(比如文件或数据库连接对象)作为参数传递,或者需要自己创建一个。如果函数需要自己打开文件,则最佳实践通常是:
with open(myfile) as fh:
# do stuff with open file handle...
为确保在
with
块退出时文件始��关闭。但是,如果传递了现有的文件句柄,则该函数可能不应该关闭它本身。考虑以下函数,它以打开的文件对象或给定文件路径的字符串作为其参数。如果传递文件路径,则应按照上述方式编写。否则应省略
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...
这样做是可行的,但除非有一个内置对象来完成这个任务(我认为没有),否则我要么必须到处复制粘贴该对象,要么总是需要导入我的自定义实用程序模块。我感觉可能有一种更简单的方法,但我可能错过了。
foo
中,你所做的大部分工作是将参数转换为正确类型的对象——一个打开的文件句柄。将执行核心工作的代码提取到一个辅助函数中,假设该函数已经有了一个打开的文件句柄,我认为整体结果更清晰。实际上,“helper” 可以成为一个合法的公共函数,而“foo_from_path”只需在打开文件句柄后调用“foo”。 - jmenp.load
可以接受字符串或文件对象作为参数(参考链接:http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.load.html)。我想这只是为了让代码更简洁,而且由于 numpy 经常被交互使用,这也不是不明智的做法。 - jme