How to subclass an OrderedDict?
python dict的子类化按预期工作:
| 12
 3
 4
 5
 6
 
 | >>> class DictSub(dict):...     def __init__(self):
 ...         self[1] = 10
 ...
 >>> DictSub()
 {1: 10}
 | 
但是,对collections.OrderedDict执行相同的操作不起作用:
| 12
 3
 4
 5
 6
 7
 8
 
 | >>> import collections>>> class OrdDictSub(collections.OrderedDict):
 ...     def __init__(self):
 ...         self[1] = 10
 ...
 >>> OrdDictSub()
 (…)
 AttributeError: 'OrdDictSub' object has no attribute '_OrderedDict__root'
 | 
因此,ordereddict的实现使用一个私有的__root属性,它防止子类OrdDictSub的行为类似于DictSub子类。为什么?一个人如何能从有序的信息技术中继承?
 
你需要从你的__init__中调用OrderedDict.__init__:
| 12
 3
 
 | class OrdDictSub(collections.OrderedDict):def __init__(self):
 super(OrdDictSub, self).__init__()
 | 
您没有给OrderedDict一个初始化自身的机会。从技术上讲,您也希望为您的dict子类执行此操作,因为您需要一个完全初始化的dict。事实上,没有它,dict就可以工作,这只是运气。
		
		
- 谢谢。是我的错。的确,我受到了dict的影响。我之前甚至问过一个关于dict的问题(stackoverflow.com/questions/2033150/…)!
- 你不想让args和kwargs进入初始状态吗?def __init__(self, *args, **kwargs):         super(OrdDictSub, self).__init__(*args, **kwargs)
 
	 
尝试在__init__方法中初始化超类:
| 12
 3
 
 | def __init__(self):collections.OrderedDict.__init__(self)
 self[1] = 10
 | 
这是初始化子类的正常方法。一般来说,您不必调用超类的__init__方法,但是如果您不知道超类的实现,那么您真的应该调用__init__。
		
		
- 使用super()调用超类方法
- @阿斯蒂纳克斯:两种方法都有效,所以这是一种风格问题。
- @Dietrichepp:答案不错,但是使用super()并不是一个风格问题:在您自己的类是子类的情况下使用它(而不是使用显式超类)是很重要的。参考示例:rhettinger.wordpress.com/2011/05/26/super-considered-super。此外,使用super()使代码的维护更加容易(更容易更改类的名称)。
- @EOL:我可以接受,super()是一种方式,但我不同意你的"进一步":我认为在python 2中,它是另一个半打中的六个。如果您想更改OrdDictSub类的名称,但仍保留相同的父类,那么使用super()意味着您必须在两个位置进行更改,而不是只在一个位置进行更改。另一方面,如果你想保留OrdDictSub的名称,但改变了父项,那么不使用super()意味着你必须在两个地方而不是一个地方进行。幸运的是,这是在python 3中修复的(只需调用super(),不带参数)。
- @约翰尼:同意,关于super()的问题,在python 2中类名更改时不太方便,只在python 3中方便。
- @约翰尼:嗯,我测试过了,使用self.__class__是错误的,因为self.__class__总是给出实际的类!这是一个你可以自己尝试的演示,当超过最大递归深度时,它会抛出一个RuntimeError:gist.github.com/depp/87a5f1079556eb0ed07e
- @约翰尼:但是你只能知道,如果你知道你的课程永远不会被分为子类是安全的,我认为大多数时候这不是一个很好的假设。
- @约翰尼:不应该说如果你使用super(),其他的就用螺丝钉固定,如果不使用的话。你可以把super()和直接的基类调用混合在一起,只要你不在一个有多个到基类路径的类中这样做(在这种情况下,你必须使用super())。在常见的情况下,唯一经常出错的是super(self.__class__, self),这就是为什么您不应该使用它。
- @约翰尼:马蒂金·彼得斯的这一极好的回答涵盖了这一点:stackoverflow.com/a/18208725/82294——如果你认为马蒂金是错的,就去那边争论。
- @迪特里切普:好的,很公平。这确实是马蒂的一个很好的解释。我删除了我在这里的一些评论,因为我认为它们对未来的读者没有帮助,即使在历史的能力(除了作为我无知的证据)。