2012-09-29 51 views
8

Possible Duplicate:
Subclassing Python tuple with multiple __init__ arguments如何在Python中初始化元組的一個子類的實例?

我想定義從tuple繼承的類,並且我希望能夠使用不受tuple支持的語法來實例化。舉一個簡單的例子,假設我想定義一個類MyTuple,它繼承自tuple,我可以通過傳遞兩個值xy來實例化,以創建(我的)元組(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。

+3

您可能需要查看[''collections.namedtuple()''](http://docs.python.org/dev/library/collections.html#collections.namedtuple)。 –

+2

請檢查[這個原始的SO問題](http://stackoverflow.com/questions/1565374/subclassing-python-tuple-with-multiple-init-arguments)的全面答案(1)爲什麼你需要使用' __new__'而不是'__init__'(2)你需要遵循什麼其他步驟。 –

回答

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建議,你可以定義一個namedtuple,

import collections 
MyTuple = collections.namedtuple('MyTuple', 'x y') 

p = MyTuple(2,3) 
print(p) 
# MyTuple(x=2, y=3) 
print(p.x) 
# 2 
+5

你可以使用'* tuple'(或'* args')而不是'x,y',那麼它會推廣到任意大小。 –

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)

+0

有趣。花了我一些時間來了解字段分配和lambda表達式的外觀。爲什麼你不使用普通的'def'結構?另外,您如何「將所有未知方法查找轉發給'_tuple'」? – Tom

+0

lambdas沒有特別的理由,我只是喜歡「綁定」這樣的功能。 'count = lambda:...'對我說「count is to be count of _tuple」。 – ch3ka

+2

你可以用'def __getattr __(self,attr)轉發未知方法查找: \t \t return self._tuple .__ getattribute __(attr)' – ch3ka