代码之家  ›  专栏  ›  技术社区  ›  Bite code

为什么不能从python中的dict和exception继承?

  •  18
  • Bite code  · 技术社区  · 16 年前

    我上了以下课:

    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(),因为异常是基于旧类的…

    编辑:是的,我尝试切换继承/init的顺序。

    我在Ubuntu8.10上使用了cpython 2.4。你知道这种信息有用吗?—)。不管怎样,这个小谜语把我3个同事的嘴闭上了。你会是我今天最好的朋友…

    6 回复  |  直到 9 年前
        1
  •  21
  •   user3850    16 年前

    两个 Exception dict 在C中实现。

    我想你可以用以下方法来测试:

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

    自从 例外 双关语 对于如何在内部存储数据有不同的想法,它们不兼容,因此您不能同时从两者继承数据。

    在后面的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
    
        2
  •  4
  •   S.Lott    16 年前

    这是怎么回事?

    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'>
    
        3
  •  3
  •   Bite code    13 年前

    没有理由,只有解决办法

    目前我还不知道为什么,但我用 UserDict.UserDict .因为它是纯Python,所以速度较慢,但我认为在应用程序的这个部分,它不会很麻烦。

    仍然对答案感兴趣;-)

        4
  •  3
  •   vaultah    9 年前

    什么版本的python?

    在2.5.1中,我甚至无法定义继承自这两个类的类 dict 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
    

    如果您使用的是较旧的版本,那么在类型定义期间可能不会进行这种检查,冲突会在以后导致异常。

        5
  •  0
  •   lispmachine    15 年前

    我几乎可以肯定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中,异常(旧样式类)和dict(新样式类)的多重继承 结果是新的样式类,这是不允许作为异常的(不管怎样,混合旧样式类和新样式类可能是不好的)。

        6
  •  0
  •   codeMonkey    9 年前

    使用 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()