针对同一列表使用不同过滤器处理多个 for 循环的 Pythonic 方法?
Pythonic way to process multiple for loops with different filters against the same list?
这是我正在编写的一些程序,它将创建一个 csv 文件目录分类:
matches = []
for root, dirnames, filenames in os.walk(directory):
for filename in fnmatch.filter(filenames, '*[A-Z]*'):
matches.append([os.path.join(root, filename), "No Capital Letters!"])
test = re.compile(".*\.(py|php)", re.IGNORECASE)
for filename in filter(test.search, filenames):
matches.append([os.path.join(root, filename), "Invalid File type!"])
基本上,用户选择一个文件夹,程序表示有问题的文件,可以是几种类型(这里只列出两种:没有大写字母的文件,没有 php 或 python 文件).大概会有五六例。
虽然这可行,但我想重构。是否可以做类似
的事情
for filename in itertools.izip(fnmatch.filter(filenames, '*[A-Z]*'), filter(test.search, filenames), ...):
matches.append([os.path.join(root, filename), "Violation")
同时能够跟踪哪些原始解压缩列表导致 "violation?"
一个更简单的解决方案可能是先遍历文件,然后一个一个地应用检查:
reTest = re.compile(".*\.(py|php)", re.IGNORECASE)
for root, dirnames, filenames in os.walk(directory):
for filename in filenames:
error = None
if fnmatch.fnmatch(filename, '*[A-Z]*'):
error = 'No capital letters!'
elif reTest.search(filename):
error = 'Invalid file type!'
if error:
matches.append([os.path.join(root, filename), error])
这不仅会使逻辑更简单,因为您只需要检查一个文件(而不是每次都必须弄清楚如何对一系列文件名调用检查方法),它还会仅在文件名列表中迭代一次。
此外,它还将避免为单个文件名生成多个匹配项;它最多只会增加一个错误(第一个)。如果你不想要这个,你可以制作 error
一个列表并在你的支票中附加到它 - 当然你想将 elif
更改为 if
然后评估所有检查。
我建议你看看these slides。
David Beazley 给出了使用 yield
处理日志文件的示例。
编辑:这里有两个来自 pdf 的例子,一个没有生成器:
wwwlog = open("access-log")
total = 0
for line in wwwlog:
bytestr = line.rsplit(None,1)[1]
if bytestr != '-':
total += int(bytestr)
print "Total", total
和生成器(对于更复杂的例子,可以使用带 yield 的函数)
wwwlog = open("access-log")
bytecolumn = (line.rsplit(None,1)[1] for line in wwwlog)
bytes = (int(x) for x in bytecolumn if x != '-')
print "Total", sum(bytes)
这是我正在编写的一些程序,它将创建一个 csv 文件目录分类:
matches = []
for root, dirnames, filenames in os.walk(directory):
for filename in fnmatch.filter(filenames, '*[A-Z]*'):
matches.append([os.path.join(root, filename), "No Capital Letters!"])
test = re.compile(".*\.(py|php)", re.IGNORECASE)
for filename in filter(test.search, filenames):
matches.append([os.path.join(root, filename), "Invalid File type!"])
基本上,用户选择一个文件夹,程序表示有问题的文件,可以是几种类型(这里只列出两种:没有大写字母的文件,没有 php 或 python 文件).大概会有五六例。
虽然这可行,但我想重构。是否可以做类似
的事情for filename in itertools.izip(fnmatch.filter(filenames, '*[A-Z]*'), filter(test.search, filenames), ...):
matches.append([os.path.join(root, filename), "Violation")
同时能够跟踪哪些原始解压缩列表导致 "violation?"
一个更简单的解决方案可能是先遍历文件,然后一个一个地应用检查:
reTest = re.compile(".*\.(py|php)", re.IGNORECASE)
for root, dirnames, filenames in os.walk(directory):
for filename in filenames:
error = None
if fnmatch.fnmatch(filename, '*[A-Z]*'):
error = 'No capital letters!'
elif reTest.search(filename):
error = 'Invalid file type!'
if error:
matches.append([os.path.join(root, filename), error])
这不仅会使逻辑更简单,因为您只需要检查一个文件(而不是每次都必须弄清楚如何对一系列文件名调用检查方法),它还会仅在文件名列表中迭代一次。
此外,它还将避免为单个文件名生成多个匹配项;它最多只会增加一个错误(第一个)。如果你不想要这个,你可以制作 error
一个列表并在你的支票中附加到它 - 当然你想将 elif
更改为 if
然后评估所有检查。
我建议你看看these slides。
David Beazley 给出了使用 yield
处理日志文件的示例。
编辑:这里有两个来自 pdf 的例子,一个没有生成器:
wwwlog = open("access-log")
total = 0
for line in wwwlog:
bytestr = line.rsplit(None,1)[1]
if bytestr != '-':
total += int(bytestr)
print "Total", total
和生成器(对于更复杂的例子,可以使用带 yield 的函数)
wwwlog = open("access-log")
bytecolumn = (line.rsplit(None,1)[1] for line in wwwlog)
bytes = (int(x) for x in bytecolumn if x != '-')
print "Total", sum(bytes)