我无法弄清楚为什么当用户输入'no'时第一个包含while的循环有效以及为什么第二个实例不起作用。
我相信两个循环的构造几乎完全相同。第二次出现只是分解成另一种功能。
当用户输入'no'时,它不应该删除字符串。
这个有效。如果用户输入“否”,则不会删除任何内容。
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')
这个不起作用。如果用户输入'no',它会删除字符串。
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')
答案 0 :(得分: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)
答案 1 :(得分:2)
请参阅Joel's wiki answer,了解如何重做这一切的好例子。
但至于修复错误......
我终于意识到你的两个例子之间的差别很大。它与您执行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
块结束时,它会关闭文件。
答案 2 :(得分:1)
在我看来,问题是“no”子句中的return
。这在tmpfile.write(line)
方法执行之前退出函数,因此对我来说看起来像字符串被删除是有意义的。我不明白为什么它会在第一个函数中起作用。
答案 3 :(得分:0)
在第二种情况下,当用户键入find_and_remove
时,您只会退出no
。在第一种情况下,您将退出整个函数。
答案 4 :(得分:0)
我和Joel有同样的想法,但有点慢......无论如何,希望这是有意义的:
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()