How to subclass an OrderedDict?
python dict的子类化按预期工作:
1 2 3 4 5 6
| >>> class DictSub(dict):
... def __init__(self):
... self[1] = 10
...
>>> DictSub()
{1: 10} |
但是,对collections.OrderedDict执行相同的操作不起作用:
1 2 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__:
1 2 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__方法中初始化超类:
1 2 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——如果你认为马蒂金是错的,就去那边争论。
- @迪特里切普:好的,很公平。这确实是马蒂的一个很好的解释。我删除了我在这里的一些评论,因为我认为它们对未来的读者没有帮助,即使在历史的能力(除了作为我无知的证据)。