假设我想使用以下语法打开一个文本文件以进行读取:

with open(fname,'r') as f:
    # do something
    pass

但是,如果我检测到它以.gz结尾,我将调用gzip.open()。
if fname.endswith('.gz'):
    with gzip.open(fname,'rt') as f:
            # do something
            pass
else:
    with open(fname,'r') as f:
            # do something
            pass

如果“做某事”部分很长并且不方便在函数中编写(例如,它将创建一个嵌套的函数,无法序列化),那么基于返回的gzip.open或open调用的最短方法是什么? fname.endswith('。gz')?

最佳答案

上下文管理器有助于关闭对象。

您不必创建用作上下文管理器的对象,但是同时您可以使用with输入上下文。 open()gzip.open()调用返回一个恰好是上下文管理器的新对象,您可以在输入上下文之前创建它们:

if fname.endswith('.gz'):
    f = gzip.open(fname,'rt')
else:
    f = open(fname, 'r')

with f:
    # do something

在这两种情况下,对象在进入上下文时都返回self,因此在此无需使用as f

此外,函数是一等公民,因此您还可以使用变量存储函数,然后在with语句中调用它以创建上下文管理器和文件对象:
if fname.endswith('.gz'):
    opener = gzip.open
else:
    opener = open

with opener(fname, 'rt') as f:  # yes, both open and gzip.open support mode='rt'
    # do something

相对于这里的其他方法,这实际上并不能给您带来任何好处,但是如果您愿意,可以使用词典将扩展名映射到可调用对象。

最重要的是with calls context-manager hook methods,仅此而已,仅此而已。 with之后的表达式应该提供这种管理器,但是创建该对象不受上下文管理协议(protocol)的约束。

关于python: "with"语法,用于使用两个函数打开文件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52952345/

10-15 13:10
查看更多