为什么不能在Python中同时继承dict和Exception?

18 投票
6 回答
4648 浏览
提问于 2025-04-11 18:49

我有一个这样的类:

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(),因为 Exception 是个老旧的基类……

编辑:是的,我试过改变继承和初始化的顺序。

编辑2:我在 Ubuntu 8.10 上使用 CPython 2.4。你永远不知道这些信息是否有用;不过,这个小难题让我的三个同事都哑口无言。你今天会是我最好的朋友……

6 个回答

3

没有特别原因,只是找到了解决办法

目前我还不知道为什么会这样,但我用 UserDict.UserDict 这个方法绕过了这个问题。虽然这个方法比较慢,因为它是纯 Python 写的,但我觉得在这个应用的这个部分,速度慢也不会造成太大麻烦。

不过我还是很想知道真正的答案 ;-)

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'>
21

在C语言中实现了Exceptiondict这两个东西。

你可以用以下方法来测试这个:

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

因为Exceptiondict在内部存储数据的方式不同,所以它们不兼容,因此你不能同时从这两个类继承。

在后来的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

撰写回答