我有一个帮助导入特殊类型文件的类,以及一个允许我批量执行这些操作的“工厂”类。工厂类使用生成器,因此客户端可以遍历导入器。 我的问题是,我是否正确使用了迭代器?这是一个可以接受的成语吗?我刚开始使用Python。
class FileParser:
""" uses an open filehandle to do stuff """
class BatchImporter:
def __init__(self, files):
self.files=files
def parsers(self):
for file in self.files:
try:
fh = open(file, "rb")
parser = FileParser(fh)
yield parser
finally:
fh.close()
def verifyfiles(
def cleanup(
---
importer = BatchImporter(filelist)
for p in BatchImporter.parsers():
p.method1()
...
答案 0 :(得分:12)
你可以做一件事更简单:使用try
块而不是finally
... with
:
with open(file, "rb") as fh:
yield FileParser(fh)
只要剩下with
块,就会自动为您关闭文件。
答案 1 :(得分:7)
像你一样拥有一个生成器的方法绝对没问题。我建议你把所有课程都改成新风格(如果你使用的是Python 2,要么在模块的开头设置__metaclass__ = type
,要么将(object)
添加到你的所有基础class
}语句),因为遗产类是“邪恶的”;-);而且,为了清晰和简洁,我还建议不同地编码生成器...:
def parsers(self):
for afile in self.files:
with open(afile, "rb") as fh:
yield FileParser(fh)
但这些建议都没有以任何方式谴责使用发电机方法! - )
请注意使用afile
代替file
:后者是内置标识符,作为一般规则,最好习惯不“隐藏“你自己的内置标识符(它不会在这里咬你,但除非你养成正确的习惯,否则它将来会以许多令人讨厌的方式!)。”。
答案 2 :(得分:1)
如果你问我,设计很好,虽然最后使用它的方式并不完全是惯用的。使用catch并且可能重新引发异常(使用raise关键字单独,否则你搞乱堆栈跟踪),并且对于奖励积分,不要捕获:但是捕获异常:(否则,你抓住SystemExit和KeyboardInterrupt)。
或者简单地使用Tim Pietzcker所示的with语句。
答案 3 :(得分:0)
通常,在产生将尝试读取它的解析器对象后关闭文件是不安全的。请考虑以下代码:
parsers = list(BatchImporter.parsers())
for p in parsers:
# the file object that p holds will already be closed!
如果您没有编写长时间运行的守护程序进程,大多数情况下您不需要需要担心关闭文件 - 当程序退出时它们都会关闭,或者当文件对象被垃圾收集时。 (如果你使用CPython,那么只要对它们的所有引用都丢失,就会发生这种情况,因为CPython使用了引用计数。)
然而,注意释放资源是一个很好的习惯,所以我可能会这样编写FileParser类:
class FileParser:
def __init__(self, file_or_filename, closing=False):
if hasattr(file_or_filename, 'read'):
self.f = file_or_filename
self._need_to_close = closing
else:
self.f = open(file_or_filename, 'rb')
self._need_to_close = True
def close(self):
if self._need_to_close:
self.f.close()
self._need_to_close = False
然后BatchImporter.parsers将成为
def parsers(self):
for file in self.files:
yield FileParser(file)
或者,如果你喜欢函数式编程
def parsers(self):
return itertools.imap(FileParser, self.files)
暂且不说:如果您是Python的新手,我建议您查看Python style guide(也称为PEP 8)。两个空格的缩进看起来很奇怪。