为什么子类化元组和子类化列表之间存在这种差异?
Why this difference between subclassing tuple and subclassing list?
下面的玩具示例看起来有点奇怪,但它尽可能简单地说明了问题。
首先,没有问题的部分:
class TupleWrapper(tuple):
def __new__(cls, ignored):
return super(TupleWrapper, cls).__new__(cls, [1, 2, 3])
class TupleWrapper
接受一个任意的 returns 类似于常量 (1, 2, 3)
的类似元组的对象。例如:
>>> TupleWrapper('foo')
(1, 2, 3)
>>> TupleWrapper(8)
(1, 2, 3)
到目前为止一切顺利。
现在,考虑这个 class:
class ListWrapper(list):
def __new__(cls, ignored):
return super(ListWrapper, cls).__new__(cls, [1, 2, 3])
它与 TupleWrapper
相同,只是它子class 是 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.
谁能帮我理解这种行为差异?
是否有可能理解它,还是"just one of those quirks"一个人不得不忍受?
区别在于元组是不可变的,因此所有工作都在 __new__
中完成。列表是可变的,因此它们的构造发生在 __init__
中。您还没有覆盖 list.__init__
方法,所以它仍然像往常一样构建列表。
PS:从列表或元组这样的内置函数继承通常是一种令人沮丧和失望的体验,所以不要打扰:)
下面的玩具示例看起来有点奇怪,但它尽可能简单地说明了问题。
首先,没有问题的部分:
class TupleWrapper(tuple):
def __new__(cls, ignored):
return super(TupleWrapper, cls).__new__(cls, [1, 2, 3])
class TupleWrapper
接受一个任意的 returns 类似于常量 (1, 2, 3)
的类似元组的对象。例如:
>>> TupleWrapper('foo')
(1, 2, 3)
>>> TupleWrapper(8)
(1, 2, 3)
到目前为止一切顺利。
现在,考虑这个 class:
class ListWrapper(list):
def __new__(cls, ignored):
return super(ListWrapper, cls).__new__(cls, [1, 2, 3])
它与 TupleWrapper
相同,只是它子class 是 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.
谁能帮我理解这种行为差异?
是否有可能理解它,还是"just one of those quirks"一个人不得不忍受?
区别在于元组是不可变的,因此所有工作都在 __new__
中完成。列表是可变的,因此它们的构造发生在 __init__
中。您还没有覆盖 list.__init__
方法,所以它仍然像往常一样构建列表。
PS:从列表或元组这样的内置函数继承通常是一种令人沮丧和失望的体验,所以不要打扰:)