代码之家  ›  专栏  ›  技术社区  ›  kjo

为什么元组子类化和列表子类化之间会有这种区别?

  •  2
  • kjo  · 技术社区  · 7 年前

    下面的玩具示例看起来有点奇怪,但它尽可能简单地说明了问题。

    首先,无问题部分:

    class TupleWrapper(tuple):
        def __new__(cls, ignored):
            return super(TupleWrapper, cls).__new__(cls, [1, 2, 3])
    

    班级 TupleWrapper 接受任意的an返回类似于常量的元组对象 (1, 2, 3) . 例如:

    >>> TupleWrapper('foo')
    (1, 2, 3)
    >>> TupleWrapper(8)
    (1, 2, 3)
    

    到现在为止,一直都还不错。

    现在,考虑一下这个类:

    class ListWrapper(list):
        def __new__(cls, ignored):
            return super(ListWrapper, cls).__new__(cls, [1, 2, 3])
    

    它与 塔普勒说唱者 除了它的子类 list 而不是 tuple . 因此,我希望

    >>> ListWrapper('foo')
    [1, 2, 3]
    >>> ListWrapper(8)
    [1, 2, 3]
    

    事实上,我得到的是

    >>> ListWrapper('foo')
    ['f', 'o', 'o']
    >>> ListWrapper(8)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: 'int' object is not iterable
    

    FWIW,我使用的是Python 2.7.13。

    有人能帮我理解这种行为上的差异吗?

    有没有可能弄明白,或者说,这只是人们不得不忍受的“怪癖之一”?

    1 回复  |  直到 7 年前
        1
  •  5
  •   Ned Batchelder    7 年前

    不同的是元组是不可变的,所以所有的工作都在 __new__ . 列表是可变的,因此它们的构造发生在 __init__ . 你还没有推翻 list.__init__ 方法,因此它仍然像往常一样构造列表。

    PS:继承list或tuple之类的内置组件通常是一个令人沮丧和失望的经历,所以不用担心:)