我正在研究如何在Python中进行文件输入和输出。我编写了以下代码,从一个文件读取一个名称列表(每行一个)到另一个文件,同时根据文件中的名称检查一个名称,并将文本追加到文件中出现的名称。代码可以工作。还能做得更好吗?

我想使用with open(…语句的输入和输出文件,但不能看到他们如何可以在同一块,这意味着我需要存储在一个临时位置的名字。

def filter(txt, oldfile, newfile):
    '''\
    Read a list of names from a file line by line into an output file.
    If a line begins with a particular name, insert a string of text
    after the name before appending the line to the output file.
    '''

    outfile = open(newfile, 'w')
    with open(oldfile, 'r', encoding='utf-8') as infile:
        for line in infile:
            if line.startswith(txt):
                line = line[0:len(txt)] + ' - Truly a great person!\n'
            outfile.write(line)

    outfile.close()
    return # Do I gain anything by including this?

# input the name you want to check against
text = input('Please enter the name of a great person: ')    
letsgo = filter(text,'Spanish', 'Spanish2')

当前回答

你可以用积木来筑巢。是这样的:

with open(newfile, 'w') as outfile:
    with open(oldfile, 'r', encoding='utf-8') as infile:
        for line in infile:
            if line.startswith(txt):
                line = line[0:len(txt)] + ' - Truly a great person!\n'
            outfile.write(line)

这比您的版本更好,因为您保证即使代码遇到异常也会关闭outfile。显然你可以用try/finally来实现,但是用with才是正确的方法。

或者,正如我刚刚学到的,你可以在@steveha所描述的with语句中有多个上下文管理器。在我看来,这似乎是一个比嵌套更好的选择。

至于你的最后一个小问题,回报没有任何实际意义。我会移除它。

其他回答

你可以用积木来筑巢。是这样的:

with open(newfile, 'w') as outfile:
    with open(oldfile, 'r', encoding='utf-8') as infile:
        for line in infile:
            if line.startswith(txt):
                line = line[0:len(txt)] + ' - Truly a great person!\n'
            outfile.write(line)

这比您的版本更好,因为您保证即使代码遇到异常也会关闭outfile。显然你可以用try/finally来实现,但是用with才是正确的方法。

或者,正如我刚刚学到的,你可以在@steveha所描述的with语句中有多个上下文管理器。在我看来,这似乎是一个比嵌套更好的选择。

至于你的最后一个小问题,回报没有任何实际意义。我会移除它。

像这样使用嵌套块,

with open(newfile, 'w') as outfile:
    with open(oldfile, 'r', encoding='utf-8') as infile:
        # your logic goes right here

有时候,你可能想要打开不同数量的文件,并对每个文件都一视同仁,你可以使用contextlib来做到这一点

from contextlib import ExitStack
filenames = [file1.txt, file2.txt, file3.txt]

with open('outfile.txt', 'a') as outfile:
    with ExitStack() as stack:
        file_pointers = [stack.enter_context(open(file, 'r')) for file in filenames]                
            for fp in file_pointers:
                outfile.write(fp.read())                   

Python允许在单个with中放入多个open()语句。用逗号分隔。你的代码将是:

def filter(txt, oldfile, newfile):
    '''\
    Read a list of names from a file line by line into an output file.
    If a line begins with a particular name, insert a string of text
    after the name before appending the line to the output file.
    '''

    with open(newfile, 'w') as outfile, open(oldfile, 'r', encoding='utf-8') as infile:
        for line in infile:
            if line.startswith(txt):
                line = line[0:len(txt)] + ' - Truly a great person!\n'
            outfile.write(line)

# input the name you want to check against
text = input('Please enter the name of a great person: ')    
letsgo = filter(text,'Spanish', 'Spanish2')

不,在函数末尾显式地返回并不会得到任何东西。你可以使用return来提前退出,但你在最后有了它,函数将没有它就退出。(当然,对于返回值的函数,可以使用return来指定要返回的值。)

在Python 2.5或Python 2.6中引入with语句时,不支持与with一起使用多个open()项,但在Python 2.7和Python 3.1或更新版本中支持。

http://docs.python.org/reference/compound_stmts.html#the-with-statement http://docs.python.org/release/3.1/reference/compound_stmts.html#the-with-statement

如果你编写的代码必须在Python 2.5、2.6或3.0中运行,请像其他答案建议的那样嵌套with语句或使用contextlib.nested。