2012-10-04 38 views
1

我遇到了繼承問題。Python中的字段繼承權限

這是我的主要程序:

def main(argv): 
    rfp = reqboxfileparserng() # Inherits from reqboxfileparser() 
    rfp.importsdir = './data/' 
    if rfp.parsingasutf8_win(): 
    rfp.parsefile("./data/LRCv12.txt") 

這裏是類:

class reqboxfileparser(): 
    def __init__(self): 
    ... removed code ... 
    # Init mmap 
    self.file = None 
    self.f = None 

    def parsefile(self, filename): 
    # Public 
    self.filename = filename 

    # Init mmap 
    self.file = codecs.open(filename, encoding='utf-8', mode='r') # open(filename, 'r') 
    self.f = mmap.mmap(self.file.fileno(), 0, access=mmap.ACCESS_READ) 
    self.f.seek(0) # rewind 

    # Parsing stuff 
    self.getfunlist() 
    self.vlog(VERB_MED, "len(fun) = %d" % (len(self.funlist))) 
    self.getfundict() 
    self.vlog(VERB_MED, "fundict = %s" % (self.fundict)) 
... rest of reqboxfileparser() class code removed ... 

class reqboxfileparserng(reqboxfileparser, object): 
    def __init__(self): 
    # Public 
    reqboxfileparser.__init__(self) 
    self.fundict = {} 
    self.importsdir = '' 

    def getfunlist(self): 
    """ 
    Overrided method to load from a CSV file 
    """ 
    self.funlist = [] 

    fh = open(self.importsdir + 'in-uc-objects.csv', 'rb') 
    f = csv.reader(fh, delimiter=',') 
    ... rest of the code removed, it works fine ... 

    def getfundict(self): 
    """ 
    Fills the fundict property with a dict where each element is indexed 
    by the fun name and each value is an object from the model 
    """ 
    self.__fundict = {} 

    beginloc = self.bodystartloc() 

    # PROBLEM! 

    finalloc = super(reqboxfileparser, self).f.size() - 1 
    ... rest of the code removed ... 

正如你可以看到我有兩個班,首先是reqboxfileparser(),第二個是reqboxfileparserng ()從第一個繼承。

在主程序中,我調用了方法:parsefile(「./data/LRCv12.txt」)[未被覆蓋],後來在第二個類中調用getfundict()[overRided],但是當我嘗試訪問f .size()它總是以TypeError失敗:必須是type,而不是classobj。

這是一段時間,因爲我不開發繼承類,但如果我沒有錯,概念是正確的。我是Python的新手。

請幫忙嗎?

非常感謝。

+1

值得注意的是,Python約定是將類名稱放在CapWords中 - 檢查[python style guide](http://www.python.org/dev/peps/pep-0008/)。 –

+1

您可以發佈錯誤消息,而不是描述它嗎? – lolopop

回答

5

有手頭這裏有兩個問題:

超級老樣式類:

class reqboxfileparser():不從object繼承,因此,super(reqboxfileparser, self)總是會產生錯誤:

TypeError: must be type, not classobj 。在繼承類

不當超級電話:

你這樣做super(reqboxfileparser, self),但你通過繼承的類(reqboxfileparser)作爲第一個參數,而不是繼承類。

因此,Python會嘗試找到一個類,該類繼承自您正在尋找的f

但是,這不是你想要的:你想要一個reqboxfileparserng的祖先實現f;那將是reqboxfileparser

請參閱have a look at the documentation最常用的super調用語法。

您的解決方案

你可能已經猜到,你應該使用super(reqboxfileparserng, self)代替。

另外,你應該總是使用new-style classes(但單獨不會解決您的問題,你會得到一個不同的錯誤抱怨AttributeError: 'super' object has no attribute 'f',這將是True,爲object不提供f)。

最後一件事...

但是在這裏,你有最後一個問題!

您正在嘗試引用f,它是子類實例的屬性。當您使用super調用時,此屬性不存在,因爲它不在父類的類定義中,該調用是super調用將使用的類。 (這是在__init__方法)

我不會進入更多的細節,爲什麼這是超級的問題,但想法是基本上只使用super在類級別定義的東西。通常,方法是,所以它們是super調用的最佳候選。

這裏是描述我的意思的例子:

class reqboxfileparser(): 
    g = 'THIS IS G' 

    def __init__(self): 
     self.f = 'THIS IS F' 
     self.g = 'THIS IS NEW G' 

    def get_g(self): 
     return self.g 

class reqboxfileparserng(reqboxfileparser, object): 
    def __init__(self): 
     reqboxfileparser.__init__(self) 


    def getfundict(self): 
     print super(reqboxfileparserng, self).g # Prints "THIS IS G" 
     print super(reqboxfileparserng, self).get_g() # Prints "THIS IS NEW G" 
     print super(reqboxfileparserng, self).f # This raises an AttributeError 

if __name__ == '__main__': 
    o = reqboxfileparserng() 
    o.getfundict() 

總體而言,super通話是非常類似於使用ParentClass.stuff,只有它有多重繼承更好的交易,而應使用這個原因。

你可以看到在這裏,reqboxfileparser.f會引起AttributeError


腳註:一個classobj是一個老樣式類,一type是一種新式類。

+0

感謝您的詳細解答Thomas,但我仍然沒有完全明白。我改變了類reqboxfileparser(object),所以它從對象繼承,我改變了父= super(reqboxfileparserng,self),然後分別調用它finalloc = father.f.size() - 1.我不明白仍然得到你說的錯誤:AttributeError:'super'對象沒有屬性'f'。我不應該通過使用超級那樣引用reqboxfileparser嗎? –

+0

@AlbertDeLaFuente如果你告訴我什麼還沒有完全獲得,我可以幫助你? –

+0

對不起,我早點擊回車,我編輯了之前的帖子。再次感謝! –

2

您缺少的一點是f當前類的一個屬性。它是繼承的:當您撥打super(...).__init__()時,代碼設置fself。所以要從子類訪問它,你只需要做self.f,就像其他任何屬性一樣。

任何屬性或方法也是如此。當你的子類實際上重寫了一些東西時,你只需要使用super,並且你需要調用超類的版本。所以沒有必要撥打超級電話來訪問parsefile,例如:self.parsefile()會很好。

+0

非常感謝你的回答丹尼爾。我想我可能從一開始就忘記了自我,我認爲這是一個繼承問題......我是一個天才! =( –