2012-09-29 16 views
8

Possible Duplicate:
Subclassing Python tuple with multiple __init__ argumentsPython'da bir tuple alt sınıfının örneğini nasıl başlatılır?

I tuple devralan bir sınıf tanımlamak istiyorum ve tuple tarafından desteklenmeyen bir sözdizimi kullanılarak örneğini mümkün istiyoruz. Basit bir örnek için, tuple'dan miras alan bir MyTuple sınıfını tanımlamak istediğimi ve (benim) (x, y) (benim) tuple'ı oluşturmak için x ve y iki değerini geçerek oluşturabildiğimi söyleyebilirim. Aşağıdaki kodu denedim:

class MyTuple(tuple): 
    def __init__(self, x, y): 
     print("debug message") 
     super().__init__((x, y)) 

Ama çalıştığımızda, örneğin, MyTuple(2, 3) bir hata aldım: TypeError: tuple() takes at most 1 argument (2 given). Görünüşe göre __init__ işlevim bile çağrılmadı (aldığım hatayı temel alarak "hata ayıklama mesajım" basılmadı).

Peki bunu yapmanın doğru yolu nedir?

Python 3.2 kullanıyorum. super kullanmanın zorluklar

+3

['' collections.namedtuple() ''] 'da bir göz atmak isteyebilirsiniz (http://docs.python.org/dev/library/collections.html#collections.namedtuple). –

+2

Lütfen (bu orijinal SO sorusunu) kontrol edin (http://stackoverflow.com/questions/1565374/subclassing-python-tuple-with-multiple-init-arguments). __new__' yerine '__init__' (2) takip etmeniz gereken diğer adımlar. –

cevap

12
class MyTuple(tuple): 
    def __new__(cls, x, y): 
     return tuple.__new__(cls, (x, y)) 

x = MyTuple(2,3) 
print(x) 
# (2, 3) 

biri aynı adlı sınıfların yöntemi sonraki çağrılacak gidiyor denetlemek kalmamasıdır. Böylece tüm sınıfların yöntemleri aynı çağrı imzasını paylaşmalıdır - en azından aynı sayıda öğe. __new__'a gönderilen argüman sayısını değiştirdiğiniz için super'u kullanamazsınız.


Veya Lattyware anlaşılacağı gibi, bir namedtuple tanımlayabiliriz

,

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' (veya '* args') yerine' x, y' kullanabilirsiniz, daha sonra rasgele boyutta genelleşir. –

1

başka yaklaşım daha ziyade ondan devralan daha tuple saklanması olacaktır: Bu ne kadar pratik

>>> 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 

, ihtiyacınız olan yeteneklere ve değişikliklere bağlıdır ve isinstance(MyTuple(2, 3), tuple)'a sahip olmanız gerekir.

+0

İlginç. Saha görevlerine ve lambdalara benzeyen şeyleri anlamak için biraz zamanımı aldım. Normal 'def' yapısını kullanmadığın belli bir sebep var mı? Ayrıca, "tüm bilinmeyen yöntem aramalarını" _tuple "öğesine nasıl yönlendiriyorsunuz? – Tom

+0

lambdas için özel bir neden yok, sadece böyle işlevleri "bağlamak" istiyorum. 'count = lambda: ...' diyor bana "saymak _tuple sayılacak OLDUĞU". – ch3ka

+2

Bilinmeyen yöntem aramalarını 'def __getattr __ (self, attr) ile iletebilirsiniz: \t \t return self._tuple .__ getattribute __ (attr)' – ch3ka

İlgili konular