2011-07-16 76 views
0

我想創建一個'File'對象,當調用ReadLine()方法而不是僅字符串時,它返回'Line'對象。我還希望能夠使用包含文本文檔的絕對路徑的字符串或字符串列表來初始化File對象,並使得結果實例在任一情況下都具有相同的行爲。我可以想出如何做到這一點的唯一方法是根據輸入類型將File對象包裝到FileDoc或FileList對象周圍。這裏是解決方案的簡化版本我到目前爲止有:我該如何編寫一個類似其他動態確定類的類? (Python)

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 

然而,這似乎笨重和不Python的,因爲我必須使用Get_count()和Set_count()方法來訪問的.Count中成員File對象,而不是直接使用instance.count訪問它。有沒有更優雅的解決方案,可以讓我作爲成員訪問.count成員,而不是使用getter和setter?

此外,對於獎勵積分,我仍然試圖找出整個繼承的事情。有沒有更好的方法來構建類之間的關係?

+3

而不是爲每個可能的輸入創建一個類,爲什麼不將這兩種類型轉換爲init中的單個對象類型(如字符串列表)? –

+0

這聽起來很像你試圖重塑已經存在的功能。你知道'iter(file(「foo.txt」))'每次從foo.txt返回一行嗎?你知道StringIO模塊提供了一個將字符串轉換爲文件類對象的包裝器嗎?你真的想要解決什麼問題? – SingleNegationElimination

回答

1

爲了簡化count屬性,使用property裝飾:

@property 
def count(self): 
    return self._count # or return self.actual.count 

@count.setter 
def count(self, value): 
    self._count = value # or self.actual.count = value 

或者,如果你不希望它是一個裝飾:

count = property(Get_count, Set_count) 

至於你的繼承方案,我想沒關係;由於您使用的是File來隱藏大部分細節,因此如果需要,稍後再更改它不應太難。 @ MannyD的評論是重組的好主意;請注意,例如,file對象是可迭代的,就像列表一樣。

作爲一個側面說明,FileLine可能爲collections.namedtuple更好(只說):

Line = collections.namedtuple('Line', 'line count path') 
+0

謝謝,我認爲'property'正是我期待Python擁有的東西。你可能是對的,@ MannyD的建議將是最直接的做法。 – tel

1

我個人認爲你的類層次結構太複雜。我不確定你的代碼如何使用它,但文件似乎被過度使用。字符串列表根本就不是文件,因此我會創建一些類似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建議的屬性,但前提是您確實有理由在讀取行時更改文件讀取器的內部計數器。

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() 

沒有必要的文件( )類,因爲它不提供任何超過基類的東西,所以在這種情況下,它只是額外的代碼來維護。此外,與其比較特定的類型,通常使用isinstance(object, type)來處理派生類也更好。

在附註中,我建議遵循PEP 8樣式指南,因爲它會使您的代碼更易於閱讀。

相關問題