我得到了以下课程:
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是基于旧的类......
编辑:是的,我试图切换继承/ init的顺序。
EDIT2:我在Ubuntu8.10上使用CPython 2.4。你刚才知道这种信息是有用的;-)。无论如何,这个小谜语已经关闭了我同事的三个口。你将成为我最好的朋友......
答案 0 :(得分:21)
Exception
和dict
都在C中实现。
我认为你可以用以下方式测试:
>>> 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
答案 1 :(得分: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'>
答案 2 :(得分:3)
什么版本的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
如果您使用的是旧版本,可能在类型定义期间没有进行此检查,并且冲突会导致以后出现异常情况。
答案 3 :(得分:3)
目前我仍然不知道原因,但我使用UserDict.UserDict
绕过它。它的速度较慢,因为它是纯Python,但我不认为应用程序的这一部分会很麻烦。
仍然对答案感兴趣; - )
答案 4 :(得分: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(新样式类)的多重继承中 导致新的样式类不允许作为例外(无论如何,混合旧的和新的样式类可能都是坏的。)
答案 5 :(得分: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()