python:组织应用程序的对象模型

时间:2014-07-31 09:27:53

标签: python oop

我有以下问题。我的应用随机采用不同的文件,例如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))

但我不确定,这是正确的方法。例如。如果按照这种方式,我无法基于文件扩展名创建一种调用所需处理器的方法

3 个答案:

答案 0 :(得分:0)

在编写自定义类以执行操作之前(或替代)可能有意义的想法是确保为归档提供一致的界面 - 将zipfile.ZipFilepy7zlib.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