我有一个(递归)函数,我想接受一个字符串或一个打开的文件对象。如果参数是字符串,则该函数将打开一个文件并使用该文件对象。当我从函数返回时,最好显式关闭这个打开的文件对象,但是只有在传入一个字符串的情况下才会这样做。(想象一下,当用户传入打开的文件对象并发现他们的文件对象在某处被关闭时,用户会感到惊讶。 )。这是我目前正在使用的:
def read_file(f, param):
do_close = isinstance(f,basestring)
f = open(f, 'rb') if do_close else f
try:
info = f.read(4)
#check info here
if info == Info_I_Want(param):
return f.read(get_data(info))
else:
f.seek(goto_new_position(info))
return read_file(f,param)
except IKnowThisError:
return None
finally:
if do_close:
f.close()
如果我找不到我想要的信息,你可以假设某些时候会IKnowThisError
被提出。
这感觉非常愚蠢。有没有更好的办法?
答案 0 :(得分:3)
为什么不用包装器包装递归函数以避免开销?
def read_file(f, param):
if isinstance(f, basestring):
with open(f, 'rb') as real_f:
return read_file2(real_f, param)
else:
return read_file2(real_f, param)
def read_file2(f, param):
# Now f should be a file object
...
答案 1 :(得分:2)
如何递归调用函数?
def read_file(f, param):
if isinstance(f, basestring):
with open(f, 'rb') as real_f:
return read_file(real_f, param)
else:
# normal path
答案 2 :(得分:1)
即将推出的Python 3.3为这类问题提供了更通用的解决方案,即contextlib.ExitStack
。这允许有条件地将上下文管理器添加到当前的with-block:
def read_file(f, param):
with ExitStack() as stack:
if isinstance(f, basestring):
f = stack.enter_context(open(f, 'rb'))
# Your code here