我有以下问题。我的应用随机采用不同的文件,例如rar,zip,7z。我有不同的处理器来提取和保存它们:
现在一切都是这样的:
if extension == 'zip':
archive = zipfile.ZipFile(file_contents)
file_name = archive.namelist()[0]
file_contents = ContentFile(archive.read(file_name))
elif extension == '7z':
archive = py7zlib.Archive7z(file_contents)
file_name = archive.getnames()[0]
file_contents = ContentFile(
archive.getmember(file_name).read())
elif extension == '...':
我想切换到更加面向对象的方法,一个主要的Processor类和子类负责特定的归档。
E.g。我在考虑:
class Processor(object):
def __init__(self, filename, contents):
self.filename = filename
self.contents = contents
def get_extension(self):
return self.filename.split(".")[-1]
def process(self):
raise NotImplemented("Need to implement something here")
class ZipProcessor(Processor):
def process(self):
archive = zipfile.ZipFile(file_contents)
file_name = archive.namelist()[0]
file_contents = ContentFile(archive.read(file_name))
等
但我不确定,这是正确的方法。例如。如果按照这种方式,我无法基于文件扩展名创建一种调用所需处理器的方法
答案 0 :(得分:0)
在编写自定义类以执行操作之前(或替代)可能有意义的想法是确保为归档提供一致的界面 - 将zipfile.ZipFile
和py7zlib.Archive7z
包装到类中例如,使用getfilenames
方法。
此方法可确保您don't repeat yourself,而无需隐藏"如果你不想
,你在课堂上的操作您可能希望使用abc
作为基类,以使事情变得更加清晰。
然后,你可以简单地说:
archive_extractors= {'zip':MyZipExtractor, '7z':My7zExtractor}
extractor= archive_extractors[extension]
file_name = extractor.getfilenames()[0]
#...
答案 1 :(得分:0)
如果你有一个有两个方法的类,其中一个是__init__()
,那么rule of thumb是一个类,那么它不是一个类,而是一个伪装的函数。
在这种情况下编写类是过度的,因为你仍然必须手动使用正确的类。
由于各种档案的处理方式略有不同,因此请将每个档案包装在一个函数中;
def handle_zip(name):
print name, 'is a zip file'
return 'zip'
def handle_7z(name):
print name, 'is a 7z file'
return '7z'
等等。由于函数是Python中的第一类对象,因此可以使用扩展作为调用正确函数的键的字典;
import os.path
filename = 'foo.zip'
dispatch = {'.zip': handle_zip, '.7z': handle_7z}
_, extension = os.path.splitext(filename)
try:
rv = dispatch[extension](filename)
except KeyError:
print 'Unknown extension', extension
rv = None
在此处理KeyError
非常重要,因为dispatch
不包含所有可能的扩展名。
答案 2 :(得分:0)
如果你想坚持使用OOP,你可以给Processor
一个静态方法来决定一个类是否可以处理某个文件,并在每个子类中实现它。然后,如果需要解压缩文件,请使用基类'__subclasses__()
方法迭代子类并创建适当的实例:
class Processor(object):
@staticmethod
def is_appropriate_for(name):
raise NotImplemented()
def process(self, name):
raise NotImplemented()
class ZipProcessor(Processor):
@staticmethod
def is_appropriate_for(name):
return name[-4:] == ".zip"
def process(self, name):
print ".. handling ", name
name = "test.zip"
handler = None
for cls in Processor.__subclasses__():
if cls.is_appropriate_for(name):
handler = cls()
print name, "handled by", handler