假设我正在逐行读取文件,并希望确保某个字符(例如,表格数据中的分隔符)在每行中显示相同的次数,具体取决于它在第一行中的计数文件。我能想到的最好的方法是使用第二台发电机,但我觉得这并不意味着“应该有一台 - 最好只有一台 - 明显的做法”。使用闭包是否符合这个格言,还是有一些其他显而易见的方式我没有看到?
def check_line(char='|'):
while True:
line_count = line.count(char)
if i == 0:
correct_count = line_count
if line_count != correct_count:
print """Line %d contains %d %s, should have %d""" % (
i, line_count, char, correct_count)
yield None
with open('file.txt', 'rb') as f:
checker = check_line()
for i, line in enumerate(f):
checker.next()
### do more things with line
我试图从我的一般问题中抽象一点,因为我对惯用语实现最好奇,而不是用文件/分隔符解决这个特定问题。
答案 0 :(得分:2)
我不认为闭包或发电机是必要的。如果只使用简单的函数定义就可以完成,为什么要使用更复杂的东西呢?也许我不能理解你想要的东西,但我要做的是:
def check_lines(_file, delimiter):
correct_count = _file.readline().count(delimiter)
for line_number, line in enumerate(_file, start=2): #lets say the first line is line 1, then the first line in this for loop will be line 2
line_count = line.count(delimiter)
if line_count != correct_count:
format_args = (line_number, line_count, delimiter, correct_count)
print("""Line {} contains {} {}, should have {}""".format(*format_args))
with open(__file__, 'r') as _file:
check_lines(_file, '(')
我不知道你的功能应该实际做什么。它可以返回或生成您需要的任何信息,而不是打印到stdout。
答案 1 :(得分:2)
要摆脱全局变量,请将读取的行传递到生成器中:
def check_line(char='|'):
correct_count = None
while True:
line = yield None
line_count = line.count(char)
if not correct_count:
correct_count = line_count
if line_count != correct_count:
print """Line %d contains %d %s, should have %d""" % (
i, line_count, char, correct_count)
with open('file.txt', 'rb') as f:
checker = check_line()
for i, line in enumerate(f):
checker.next(line)
更好的解决方案是完全包装生成器:
def check_line(gen, char='|'):
correct_count = None
injected = None
while True:
i, line = gen.next(injected)
line_count = line.count(char)
if not correct_count:
correct_count = line_count
if line_count != correct_count:
print """Line %d contains %d %s, should have %d""" % (
i, line_count, char, correct_count)
injected = yield i, line
with open('file.txt', 'rb') as f:
checker = check_line(enumerate(f))
for i, line in checker:
print line