可能重复:
Subclassing Python tuple with multiple __init__ arguments
我想定义一个继承自tuple
的类,我希望能够使用tuple
不支持的语法对其进行实例化。举一个简单的例子,假设我想定义一个继承自MyTuple
的类tuple
,我可以通过传递两个值x
和y
来实例化它们。创建(我的)元组(x, y)
。我尝试过以下代码:
class MyTuple(tuple):
def __init__(self, x, y):
print("debug message")
super().__init__((x, y))
但是,当我尝试时,MyTuple(2, 3)
我收到了错误:TypeError: tuple() takes at most 1 argument (2 given)
。似乎我的__init__
函数甚至没有被调用(基于我得到的错误以及我的“调试消息”没有被打印的事实)。
那么这样做的正确方法是什么?
我正在使用Python 3.2。
答案 0 :(得分:12)
class MyTuple(tuple):
def __new__(cls, x, y):
return tuple.__new__(cls, (x, y))
x = MyTuple(2,3)
print(x)
# (2, 3)
使用super
的一个难点是,您无法控制下一个将要调用哪个类的同名方法。因此,所有类的方法必须共享相同的调用签名 - 至少相同数量的项。由于您要更改发送到__new__
的参数数量,因此无法使用super
。
或者正如Lattyware建议的那样,您可以定义一个命名元组,
import collections
MyTuple = collections.namedtuple('MyTuple', 'x y')
p = MyTuple(2,3)
print(p)
# MyTuple(x=2, y=3)
print(p.x)
# 2
答案 1 :(得分:1)
另一种方法是封装元组而不是继承它:
>>> class MyTuple(object):
count = lambda self, *args: self._tuple.count(*args)
index = lambda self, *args: self._tuple.index(*args)
__repr__ = lambda self: self._tuple.__repr__()
# wrap other methods you need, or define them yourself,
# or simply forward all unknown method lookups to _tuple
def __init__(self, x, y):
self._tuple = x,y
>>> x = MyTuple(2,3)
>>> x
(2, 3)
>>> x.index(3)
1
这是多么实用,取决于您需要多少功能和修改,以及您需要isinstance(MyTuple(2, 3), tuple)
。