3

継承に問題があります。

これは私のメインプログラムです:

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 ...

ご覧のとおり、2 つのクラスがあります。1 つ目は reqboxfileparser() で、2 つ目は最初のクラスを継承する reqboxfileparserng() です。

メインプログラムでメソッドを呼び出します: parsefile("./data/LRCv12.txt") [オーバーライドされていません] 後で 2 番目のクラスで getfundict() [オーバーライドされました] が呼び出されますが、f.size() にアクセスしようとするとTypeError: must be type, not classobj で常に失敗します。

継承を使用してクラスを開発しないようになってからしばらく経ちましたが、私が間違っていなければ、概念は正しいです。私はPythonの初心者です。

何か助けてください。

どうもありがとう。

4

2 に答える 2

6

ここには2つの問題があります。

スーパーおよびオールドスタイルのクラス:

class reqboxfileparser():から継承しないためobject、結果としてsuper(reqboxfileparser, self)常にエラーが発生します。

TypeError: must be type, not classobj

継承クラスでの不適切なスーパーコール:

を実行していますが、継承クラスではなく、super(reqboxfileparser, self)継承クラス(reqboxfileparser)を最初の引数として渡しています。

reqboxfileparser結果として、Pythonは、あなたが探しているものを実装する継承するクラスを見つけようとしますf

しかし、それはあなたが望んでいることではありません。あなたが望んでいるのは、reqboxfileparserngその実装の祖先fです。それはですreqboxfileparser

最も一般的な呼び出し構文については、ドキュメントを参照してください。super

あなたの解決策

super(reqboxfileparserng, self)おそらく、代わり に使用する必要があると今では推測しているでしょう。

さらに、常に新しいスタイルのクラスを使用する必要があります(ただし、それだけでは問題が解決しないため、提供されていないAttributeError: 'super' object has no attribute 'f'のでTrue、と文句を言う別のエラーが発生します)。objectf

最後に一つだけ...

しかし、ここで、最後の問題が1つあります。

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


脚注:aclassobjは古いスタイルのクラスであり、atypeは新しいスタイルのクラスです。

于 2012-10-04T20:07:32.917 に答える
3

あなたが見逃している点は、それが現在のクラスfの属性であることです。継承されます: を呼び出すと、コードは に設定されます。したがって、サブクラスからアクセスするには、他の属性と同じように を実行するだけです。super(...).__init__()fselfself.f

同じことが、任意の属性またはメソッドにも当てはまります。superサブクラスが実際に何かをオーバーライドした場合にのみ使用する必要があり、スーパークラスのバージョンを呼び出す必要があります。したがって、にアクセスするために super を呼び出す必要はありません。parsefileたとえば、次のself.parsefile()ようにすれば問題ありません。

于 2012-10-04T21:15:21.790 に答える