18

次のクラスを取得しました:

class ConstraintFailureSet(dict, Exception) :
    """
        Container for constraint failures. It act as a constraint failure itself
        but can contain other constraint failures that can be accessed with a dict syntax.
    """

    def __init__(self, **failures) :
        dict.__init__(self, failures)
        Exception.__init__(self)

print isinstance(ConstraintFailureSet(), Exception)
True
raise ConstraintFailureSet()
TypeError: exceptions must be classes, instances, or strings (deprecated), not ConstraintFailureSet

一体何?

そして最悪なのは、例外が古いベースのクラスであるため、super() を試すことができないことです...

編集:そして、はい、継承/初期化の順序を切り替えようとしました。

EDIT2:Ubuntu8.10でCPython 2.4を使用しています。この種の情報が役立つことを最近知っています;-)。とにかく、この小さななぞなぞは、3 人の同僚の口を閉ざしてしまいました。あなたは今日の私の親友になるでしょう...

4

6 に答える 6

21

Exceptionとは両方ともdictC で実装されています。

これは次の方法でテストできると思います。

>>> class C(object): pass
...
>>> '__module__' in C.__dict__
True
>>> '__module__' in dict.__dict__
False
>>> '__module__' in Exception.__dict__
False

Exceptionとはデータを内部に保存する方法について異なる考えを持っているためdict、互換性がなく、両方から同時に継承することはできません。

それ以降のバージョンの Python では、クラスを定義しようとすると例外が発生するはずです。

>>> class foo(dict, Exception):
...     pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
    multiple bases have instance lay-out conflict
于 2008-11-21T17:30:50.357 に答える
4

これの何が問題なのですか?

class ConstraintFailure( Exception ):
    def __init__( self, **failures ):
        self.failures= failures # already a dict, don't need to do anything
    def __getitem__( self, key ):
        return self.failures.get(key)

これは例外であり、 という名前の内部辞書に他の例外が含まれていますfailures

問題を更新して、これができない特定のことをリストしていただけますか?

try:
    raise ConstraintFailure( x=ValueError, y=Exception )
except ConstraintFailure, e:
    print e['x']
    print e['y']


<type 'exceptions.ValueError'>
<type 'exceptions.Exception'>
于 2008-11-21T21:35:39.440 に答える
3

Pythonのどのバージョンですか?

dict2.5.1では、との両方から継承するクラスを定義することさえできませんException

>>> class foo(dict, Exception):
...   pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
    multiple bases have instance lay-out conflict

古いバージョンを使用している場合は、型の定義中にこのチェックが行われず、競合によって後で奇妙なことが発生する可能性があります。

于 2008-11-21T15:55:23.060 に答える
3

理由はありませんが解決策

今のところ理由はわかりませんが、を使用してバイパスしUserDict.UserDictます。純粋なPythonなので遅いですが、アプリのこの部分では面倒になるとは思いません。

とにかく答えにまだ興味があります;-)

于 2008-11-21T16:00:08.230 に答える
0

2.4 の問題は、例外が古いスタイルのクラスであることが原因であることはほぼ確実です。

$ python2.4
Python 2.4.4 (#1, Feb 19 2009, 09:13:34)
>>> type(dict)
<type 'type'>
>>> type(Exception)
<type 'classobj'>
>>> type(Exception())
<type 'instance'>

$ python2.5
Python 2.5.4 (r254:67916, Feb 17 2009, 23:11:16)
>>> type(Exception)
<type 'type'>
>>> type(Exception())
<type 'exceptions.Exception'>

メッセージが示すように、両方のバージョンで、例外はクラス、インスタンス (古いスタイルのクラス)、または文字列 (非推奨) である可能性があります。

バージョン 2.5 から、例外階層は最終的に新しいスタイル クラスに基づいています。また、BaseException から継承する新しいスタイル クラスのインスタンスも許可されるようになりました。しかし、2.4 では、Exception (古いスタイル クラス) と dict (新しいスタイル クラス) からの多重継承により、例外として許可されない新しいスタイル クラスが生成されます (古いスタイル クラスと新しいスタイル クラスを混在させることは、いずれにせよ悪いことです)。

于 2009-05-29T08:22:38.793 に答える
0

collections.UserDictメタクラスの競合を避けるために使用します。

class ConstraintFailureSet(coll.UserDict, Exception):
        """
            Container for constraint failures. It act as a constraint failure itself
            but can contain other constraint failures that can be accessed with a dict syntax.
        """

        def __init__(self, **failures) :
            coll.UserDict.__init__(self, failures)
            Exception.__init__(self)


print( isinstance(ConstraintFailureSet(), Exception)) #True
raise ConstraintFailureSet()
于 2015-12-17T12:30:02.037 に答える