2012-10-04 39 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

非常感谢你的回答丹尼尔。我想我可能从一开始就忘记了自我,我认为这是一个继承问题......我是一个天才! =( –