web-dev-qa-db-ja.com

Python super()の動作は信頼できません

何らかの理由で、super()メソッドは常に期待どおりに動作するとは限らず、以下を返すように選択します。

_TypeError('super(type, obj): obj must be an instance or subtype of type)'
_

エラー手段の意味を理解しています。なぜエラーになるのかわかりません。壊れているコードの断片を以下に示します。システム内のすべてのオブジェクトは、新しいスタイルのオブジェクトです。

本当に興味深いのは、このエラーがalwaysを表示しないことです。何が原因なのかわかりません。 Retrievalsuper()メソッドはRetrievalクラスを渡し、それ自体をオブジェクトとして渡します。これは、私が知る限り、super() is supposedが呼び出されます。

何か考えはありますか?

ファイル内DBConnection.py

_class DBAdminConnection(object):
    def __init__(self):
        self.user = DBUserConnection().user 
        self.submissions = DBSubmissionConnection()
_

ファイル内Retrieval.py

_class Retrieval(DBConnection.DBAdminConnection): 
    def __init__(self, username=None, password=None, unique_key=None):
        super(Retrieval,self).__init__()
        if username and password:
            self.username = username
            self.user.login(username,password, config.DATABASE)
            if self.user.error:
                raise UserLoginError(username)
        self.unique_key = unique_key
_
41

途中でモジュールをリロードしていますか?もしそうなら、それはこのエラーを説明するかもしれません。

明らかに、メモリ参照の変更により、モジュールのリロード後にisinstance(self,DBAdminConnection)がfalseになる場合があります。

編集:mod_wsgiの下でweb.pyアプリを実行している場合は、自動再読み込みを無効にしていることを確認してください:

app = web.application(urls, globals(), autoreload=False)
57
Eduardo Ivanec

ワークフローの一部としてreload()を使用している場合、継承の初期化にはsuper(self.__class__, self).__init__も使用する必要があるようです。

このバグはid(self.__class__) ==id(Retrieval)の失敗と同時に発生すると思われます。

12
Hal Meyers

私はちょうど同じ問題を抱えており、jupyter Notebookでコードを実行しています。私はリロードを使用していたので、カーネルを再起動して、Eduardo Ivanecの応答を追跡し、これが問題であるかどうかを確認しました。それから私のコードは壊れました。私の問題が継承のいくつかのレイヤーに関連していることを発見しました。ここでは、最下層が定義されていますaboveモジュールの2番目の最下層。

class MyClass1(object):
'''example class 1'''

class MyClass2(MyClass1):
'''example class 2'''
    def __init__(self):
    super(MyClass2, self).__init__()

class MyClass4(MyClass3):
'''example class 4 - no __init__ definition'''

class MyClass3(MyClass2):
'''example class 3 - no __init__ definition'''

MyClass4をMyClass3の下に移動すると、問題が解決しました。

これはルーキーの間違いである可能性が高いため、上記の元の問題の原因を解決できない可能性がありますが、私のような他のルーキーが同じ間違いを犯している場合に備えて投稿すると思います。

(私のスタイルが間違っている場合はお詫びします。これはスタックオーバーフローに関する私の最初の投稿です。)

1
ahnastin

エラーが発生している理由はわかりませんが、デバッグの助けとして、superへの呼び出しをtry/exceptブロックし、例外が発生したときにデータダンプを実行します。このようなもの:

class Retrieval(DBConnection.DBAdminConnection): 
    def __init__(self, username=None, password=None, unique_key=None):
        try:
            super(Retrieval,self).__init__()
        except TypeError, e:
            print "Failure initialising Retrieval --> self: %r"
            raise
        if username and password:
            self.username = username
            self.user.login(username,password, config.DATABASE)
            if self.user.error:
                raise UserLoginError(username)
        self.unique_key = unique_key
1
Ethan Furman

同じエラーが発生した後、同じfile.py内に重複したクラス(私の間違い)があることに気付きました。 2番目のクラスAの名前をクラスBに変更するとエラーが消えた

#Just some example below, not real code
class A (object):

    def fun(self):
        super(A, self).fun()

class A (object): ##This second class with same name (A) caused the error

   def some_fun(self,x,y):
1
Bernard Too