0

連携方法とスーパー

superこれは、説明目的で Guido によって組み込まれた純粋な python 実装の例です。Super以下のクラスの実装について明確にする必要があります

以下のコードでは、呼び出しsomeobj.__mro__は機能しません。行に対する私のコメントを参照してください。組み込みの場合、super単純にエラーがスローされます。

TypeError: super(type, obj): obj must be an instance or subtype of type

質問:

私の質問は、そもそもその行を持つ意図は何でしたか?

したがって、渡されたオブジェクトが渡されたクラスのインスタンスでない場合は、オブジェクトの mro の使用を開始します...なぜ??

class Super(object):
        def __init__(self, type, obj=None):
            self.__type__ = type
            self.__obj__ = obj
        def __get__(self, obj, type=None):
            if self.__obj__ is None and obj is not None:
                return Super(self.__type__, obj)
            else:
                return self
        def __getattr__(self, attr):
            if isinstance(self.__obj__, self.__type__):
                starttype = self.__obj__.__class__
            else:
                starttype = self.__obj__   ## This line does not work
            mro = iter(starttype.__mro__)
            for cls in mro:
                if cls is self.__type__:
                    break
            # Note: mro is an iterator, so the second loop
            # picks up where the first one left off!
            for cls in mro:
                if attr in cls.__dict__:
                    x = cls.__dict__[attr]
                    if hasattr(x, "__get__"):
                        x = x.__get__(self.__obj__)
                    return x
            raise AttributeError, attr

class A(object):
        def m(self):
            '''  m in A'''
            return "A"

class B(A):
        def m(self):
            '''  m in B'''
            return "B" + Super(B, self).m()

class C(A):
        def m(self):
            ''' m in C '''
            return "C" + Super(C, self).m()

class D(C):
        def m(self):
            ''' m in D'''
            return "D" + Super(B, self).m()

print D().m() # "DCBA"

スタックトレース:

Traceback (most recent call last):
  File "./supertest.py", line 73, in <module>
    print D().m() # "DCBA"
  File "./supertest.py", line 71, in m
    return "D" + Super(B, self).m()
  File "./supertest.py", line 33, in __getattr__
    mro = iter(starttype.__mro__)
AttributeError: 'D' object has no attribute '__mro__'
4

2 に答える 2

6

TypeError: super(type, obj): obj must be an instance or subtype of type

あなたが渡したオブジェクトobjは古いスタイルのオブジェクト (古いスタイルのクラスのインスタンス) でした。これらはすべて 型classobjを持ち、 のサブクラスでobjectはなく、型type(または のサブクラスtype) ではありません。

古いスタイルのオブジェクトの説明では、取り消し線が引かれたテキストは正しいですが、完全なコードと例外を見て、これはその例外を引き起こしている問題ではありません。上記の例外はsuper、以下に示す間違いをキャッチする組み込みの例外です:Dは のサブクラスではないBため、superその入力のペアでは何もできないことを示しています。

私の質問は、そもそもその行を持つ意図は何でしたか?

トレースバックをトリガーする問題 (上記の最初のエラーではなく完全なトレースバック) はD、 のサブクラスではないことですB

このコードでは:

if isinstance(self.__obj__, self.__type__):
    starttype = self.__obj__.__class__
else:
    starttype = self.__obj__   ## This line does not work
mro = iter(starttype.__mro__)

__obj__が のインスタンスではない場合、 はそれ__type__自体__obj__が型であり、mro があると想定されています。の基底クラス (またはクラス) では__obj__ない型を提供する場合のハンドラーはありません。superSuper

ここでの唯一の設計上の欠陥は、コンストラクターがおそらくこのケースをキャッチし、適切な例外を生成する必要があることです。

最後に、あなたが投稿したコードは、リンク先のドキュメント内のコードと同じではないことに注意してください。Guido のコードは、実際にはこの問題を引き起こしません。

于 2013-09-05T15:25:49.160 に答える
0

今わかりました。Builtinsuperはそのように呼び出すことができます: super(type, type2)type2 が type のサブクラスである必要があります。Super実装では、そのように呼び出されるとSuper(type, type2) isinstance(type2, type)失敗し、type2 のmroが評価されます。したがって、基本的にスーパーはビルトインと同等の機能を持とうとしています

于 2013-09-06T05:58:52.167 に答える