在元组的子类中,`tuple .__ init__`与`super().__ init__`有什么不同?

时间:2017-12-04 05:55:16

标签: python

请参阅以下代码:

#! /usr/bin/env python3

class MyTupleT(tuple):
    def __init__(self, contents):
        tuple.__init__(contents)
        self.len = len(contents)

class MyTupleS(tuple):
    def __init__(self, contents):
        super().__init__(contents)
        self.len = len(contents)

t = MyTupleT([0, 1, 2])
print(t.len, t)

s = MyTupleS([0, 1, 2])
print(s.len, s)

输出结果为:

3 (0, 1, 2)
Traceback (most recent call last):
File "tuple_init.py", line 16, in <module>
    s = MyTupleS([0, 1, 2])
File "tuple_init.py", line 10, in __init__
    super().__init__(contents)
TypeError: object.__init__() takes no parameters
super()

The docs say

  

返回一个代理对象,该方法将方法调用委托给类型为

的父类或兄弟类
这里的{IUC} super()super(MyTupleS, self)相同。现在,文档进一步说明了

  

搜索顺序与getattr()使用的搜索顺序相同,只是跳过了类型本身。该类型的__mro__属性列出了getattr()super()使用的方法解析搜索顺序。

哦,但随后:

$ MyTupleS.__mro__
(__main__.MyTupleS, tuple, object)

因此,super()行应首先在tuple内查找__init__,而元组__init__肯定可以使用一个参数({{1}除外)当然)并且是显式self行调用的内容。那么为什么tuple.__init__通话工作与此相同呢?为什么要尝试调用super().__init__并失败?

IIUC只需要在担心继承层次结构可以在动态执行环境中发生变化时,只需要明确指定超类。 (来自文档的短语)并希望调用特定超类的方法。但是这个错误实际上使得必须指定超类。为什么呢?

注意:这与another similarly titled question不同。

1 个答案:

答案 0 :(得分:2)

如果您致电tuple.__init__,则会返回object.__init__,因为tuple没有自定义__init__方法,只会从object继承。 object.__init__的第一个参数是selfobject.__init__的作用是什么。因此,当您传入contents时,它被解释为self并且不会抛出异常。但是它可能不会按照您的想法执行,因为tuple.__new__负责设置新的元组实例。

如果您使用super().__init__它也会解析为object.__init__,但它已将当前的“self”绑定为第一个参数。因此,当您将contents传递给此函数时,它被解释为object.__init__不存在的附加参数,因此会抛出该错误。