0

我无法弄清楚为什么当用户输入“否”时第一个包含 while 的 for 循环有效,以及为什么第二个实例无效。

我相信这两个循环的构造几乎相同。第二次出现只是分解为另一个功能。

当用户输入“否”时,它应该不会删除字符串。

这个有效。如果用户输入“否”,它不会删除任何内容。

def remove():
    f = open('codilist.txt')
    coname = raw_input('What company do you want to remove? ') # company name
    tmpfile = open('codilist.tmp', 'w')
    for line in f:
        if coname.upper() in line:
            while True:
                answer = raw_input('Are you sure you want to remove company?\nyes or no?')
                if answer == 'yes':
                    print line.upper() + '...has been removed.'
                    break                
                elif answer == 'no':
                    f.close()
                    tmpfile.close()
                    return
                else:
                    print 'Please choose yes or no.'                    
        else:
            tmpfile.write(line)
    f.close()
    tmpfile.close()
    os.rename('codilist.tmp', 'codilist.txt')

这个不行。如果用户输入“否”,它无论如何都会删除该字符串。

def find_and_remove(f,coname,tmpfile):
    for line in f:
        if coname.upper() in line:
            while True:
                answer = raw_input('Are you sure you want to remove company?\nyes or no?')
                if answer == 'yes':
                    print line.upper() + '...has been removed.'
                    break               
                elif answer == 'no':
                    f.close()
                    tmpfile.close()
                    return
                else:
                    print 'Please choose yes or no.'                   
        else:
            tmpfile.write(line)

def remove():
    f = open('codilist.txt')
    coname = raw_input('What company do you want to remove? ') # company name
    tmpfile = open('codilist.tmp', 'w')
    find_and_remove(f,coname,tmpfile)
    f.close()
    tmpfile.close()
    os.rename('codilist.tmp', 'codilist.txt')
4

5 回答 5

3

为了展示更好的编码风格,我冒昧地在下面重写了您的脚本:

def get_user_in(message, valid_responses):
    while True:
        user_in = raw_input(message)
        if user_in in valid_responses:
            return user_in
        else:
            print "Please choose from: {0} or {1}".format(*valid_responses)

def find_and_remove(co_name, infile, outfile):
    pattern = co_name.upper()
    for line in infile:
        if pattern in line.upper():
            print line
            answer = get_user_in("Remove this line? ", ("yes", "no"))
            if answer == "no":
                outfile.write(line)
        else:
            outfile.write(line)

def remove(filename):
    outFilename = filename + '.tmp'
    with open(filename, 'r') as infile, open(outFilename, 'w') as tmpfile:
        co_name = raw_input('What company do you want to remove? ')
        find_and_remove(co_name, infile, tmpfile)
    os.rename(outFilename, filename)
于 2012-07-08T21:56:24.173 回答
2

有关如何重做整个事情的一个很好的例子,请参阅Joel 的 wiki 答案。

但至于修复你的错误......

我终于意识到你的两个例子之间的巨大差异是什么。它与您执行rename.

在您的第一个示例中,当用户说“不”时,从整个函数返回会阻止您os.rename发生任何事情。结果是您看到一个完全不变的原始 .txt 文件。

在你的第二个例子中,如果用户说“不”,你会从子函数返回到主函数,但os.rename不管发生了什么。这意味着如果他们说不,您不再写任何行,但您仍然会复制已处理一半的 tmp 文件。

虽然我真的认为应该重写整个事情,但对当前代码的一个简单调整是find_and_remove返回过程是否成功,可能带有 bool:

def find_and_remove(f,coname,tmpfile):
    ...             
                elif answer == 'no':
                    return False
    return True

def remove():
    ...
    success = find_and_remove(f,coname,tmpfile)
    f.close()
    tmpfile.close()
    if success:
        os.rename('codilist.tmp', 'codilist.txt')

老实说,您应该考虑使用with上下文来打开和关闭文件,这样您就不必混淆何时关闭文件的一堆条件。你让它们在两个不同的功能中被关闭。

with语句_

with open('infile.txt') as inFile, open('outfile.txt', 'w') as outFile:
    for line in inFile:
        outFile.write(line)

with块结束时,它会关闭文件。

于 2012-07-08T21:52:53.490 回答
1

在我看来,问题出return在“否”子句中。在方法执行之前退出函数tmpfile.write(line),所以对我来说看起来字符串被删除是有意义的。我不明白为什么它会在第一个函数中起作用。

于 2012-07-08T21:37:35.747 回答
0

我和乔尔有同样的想法,但有点慢......无论如何,希望这是有趣的:

COMPANY_FILE = 'codilist.txt'

def load_companies():
    with open(COMPANY_FILE) as inf:
        return filter(None, (line.strip() for line in inf))

def save_companies(companies):
    with open(COMPANY_FILE, 'w') as outf:
        outf.write('\n'.join(companies))

def get_option(prompt, options):
    options = [opt.strip().lower() for opt in options]
    prompt = "{}? [{}]".format(prompt, '/'.join(options))
    options = set(options)
    while True:
        res = raw_input(prompt).strip().lower()
        if res in options:
            return res

def remove_company(remove, companies):
    ask = lambda c: get_option('Remove company {}'.format(c), ['yes', 'no'])
    return [co for co in companies if remove not in co or ask(co)=='no']

def main():
    companies = load_companies()
    co_len = len(companies)

    remove = raw_input('Name of company to remove?').strip()
    companies = remove_company(remove, companies)

    if len(companies) < co_len:
        save_companies(companies)

if __name__=="__main__":
    main()
于 2012-07-08T22:04:02.360 回答
0

在第二种情况下,您仅find_and_remove在用户键入时才返回no。在第一种情况下,您将退出整个函数。

于 2012-07-08T21:34:49.923 回答