2017-02-22 85 views
8

To pytanie jest przeciwieństwem Inherit namedtuple from a base class in python, gdzie celem jest dziedziczenie podklasy od nazwanego, a nie odwrotnie.Dziedziczenie z nazwanej, pomniejszej klasy bazowej - Python

W normalnym dziedziczenia, to działa:

class Y(object): 
    def __init__(self, a, b, c): 
     self.a = a 
     self.b = b 
     self.c = c 


class Z(Y): 
    def __init__(self, a, b, c, d): 
     super(self.__class__, self).__init__(a, b, c) 
     self.d = d 

[out]:

>>> Z(1,2,3,4) 
<__main__.Z object at 0x10fcad950> 

Ale jeśli klasy bazowej jest namedtuple:

from collections import namedtuple 

X = namedtuple('X', 'a b c') 

class Z(X): 
    def __init__(self, a, b, c, d): 
     super(self.__class__, self).__init__(a, b, c) 
     self.d = d 

[out]:

>>> Z(1,2,3,4) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: __new__() takes exactly 4 arguments (5 given) 

Pytanie, jest możliwe dziedziczenie liter w języku Python jako klasy podstawowej? Czy tak, jak?

Odpowiedz

12

Można, ale trzeba zastąpić __new__ który nazywa się niejawnie przed __init__:

class Z(X): 
    def __new__(cls, a, b, c, d): 
    self = super(Z, cls).__new__(cls, a, b, c) 
    self.d = d 
    return self 

>>> z = Z(1, 2, 3, 4) 
>>> z 
Z(a=1, b=2, c=3) 
>>> z.d 
4 

Ale d będzie tylko niezależna atrybut!

>>> list(z) 
[1, 2, 3] 
+0

mogę zrobić 'self.append (d)'? – alvas

+0

@alvas Nie, ponieważ 'namedtuple' jest po prostu" krotką "(niezmienną przez konstrukcję i dlatego nie ma' append') – MSeifert

+0

@Mseifert Dzięki! Ale = ( – alvas

3

myślę, że można osiągnąć to, co chcesz o tym wszystkich pól w oryginalnej nazwie krotki, a następnie dostosowanie liczby argumentów użyciu __new__ jak schwobaseggl sugeruje powyżej. Na przykład, aby zająć sprawę Max, gdzie niektóre wartości wejściowych są obliczane zamiast dostarczanego bezpośrednio następujące prace:

from collections import namedtuple 

class A(namedtuple('A', 'a b c computed_value')): 
    def __new__(cls, a, b, c): 
     computed_value = (a + b + c) 
     return super(A, cls).__new__(cls, a, b, c, computed_value) 

>>> A(1,2,3) 
A(a=1, b=2, c=3, computed_value=6)