如何编写一个行为与另一个动态确定的类完全相同的类? (蟒蛇)

时间:2011-07-16 21:03:54

标签: python inheritance object input io

我想创建一个'File'对象,当调用ReadLine()方法而不仅仅是字符串时,它返回'Line'对象。我还希望能够使用包含文本文档的绝对路径的字符串或字符串列表来初始化File对象,并使得结果实例在任何一种情况下都具有相同的行为。我可以弄清楚如何执行此操作的唯一方法是将File对象包装在FileDoc或FileList对象周围,具体取决于输入类型。这是我到目前为止解决方案的缩写版本:

class Line(object):
    def __init__(self, line, count, fpath):
        self.text = line
        self.count = count
        self.fname = fpath.split('/')[-1]

class FileBase(object):
    def __init__(self):
        pass

    def Open(self):
        self.count = 0

    def Readline(self):
        pass

    def Get_count(self):
        return self.count

    def Set_count(self, val):
        self.count = val

class FileList(FileBase):
    def __init__(self, lines):
        self.lines = lines
        self.Open()

    def ReadLine(self):
        self.count += 1
        try:
            return Line(line=self.lines[self.count - 1], count=self.count - 1, fpath='list')
        except IndexError:
            raise StopIteration

class FileDoc(FileBase):
    def __init__(self, fpath):
        self.fpath = fpath
        self.Open()

    def Open(self):
        self.count = 0
        self.file = open(self.fpath, 'r')

    def ReadLine(self):
        self.count += 1
        return Line(line=self.file.next(), count=self.count - 1, fpath=self.fpath)

class File(FileBase):
    def __init__(self, input):
        if type(input) == type(''):
            self.actual = FileDoc(input)
        elif type(input) == type([]):
            self.actual = FileList(input)
        else:
            raise NonRecognizedInputError

    def Open(self):
        self.actual.Open()

    def ReadLine(self):
        return self.actual.ReadLine()

    def Get_count(self):
        return self.actual.count

    def Set_count(self, val):
        self.actual.count = val

但是,这似乎很笨拙而且非Pythonic,因为我必须使用Get_count()和Set_count()方法来访问File对象的.count成员,而不是只能使用instance.count直接访问它。 。是否有一个更优雅的解决方案,允许我作为成员而不是getter和setter访问.count成员?

另外,对于奖励积分,我仍然试图弄清楚整个继承的事情。是否有更好的方法来构建类之间的关系?

3 个答案:

答案 0 :(得分:1)

答案 1 :(得分:1)

我个人认为你的类层次结构太复杂了。我不确定你在代码中如何使用它,但是 File 这个词似乎被过度使用了。字符串列表根本不是文件,因此我创建类似LineReader的东西,以便能够从不同的源读取,而不是使用文件或列表迭代器。

请考虑以下代码:

class Line(object):
    def __init__(self, line, count, fpath):
        self.text = line
        self.count = count
        self.fname = fpath

class LineReader(object):
    def __init__(self, iterator, fname):
        self.iterator = iterator
        self.fname = fname
        self.count = 0

    def ReadLine(self):
        line = Line(self.iterator.next(), self.count, self.fname)
        self.count += 1        
        return line

class LineSource(object):
    def __init__(self, input):
        if type(input) == type(''):
            self.reader = LineReader(open(input), input.split('/')[-1])
        elif type(input) == type([]):
            self.reader = LineReader(iter(input), 'list')
        else:
            raise NonRecognizedInputError

    def ReadLine(self):
        return self.reader.ReadLine()

看起来对我来说简单得多,并且完成了这项工作。我不知道为什么你需要访问计数器,因为它写入Line对象。您可以使用@ li.davidm推荐的属性,但前提是您确实有理由在读取行时更改文件阅读器的内部计数器。

答案 2 :(得分:0)

除非有理由强制执行继承层次结构,否则我会考虑使用工厂模式并利用Python动态类型化的事实:

def FileFactory(input):
    if isinstance(input, types.StringTypes):
        return FileDoc(input)
    if isinstance(input, (types.ListType, types.TupleType)):
        return FileList(input)
    raise NonRecognizedInputError()

不需要File()类,因为它不提供基类的任何内容,因此在这种情况下,它只是需要维护的额外代码。此外,不是比较特定类型,通常最好使用isinstance(object, type)来处理派生类。

在旁注中,我建议您遵循PEP 8样式指南,因为这样可以让您的代码更易于阅读。