この質問は、 Pythonの基本クラスからnamedtupleを継承する の反対を求めています。ここでの目的は、namedtupleからサブクラスを継承することであり、その逆ではありません。
通常の継承では、これは機能します:
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(Z, self).__init__(a, b, c)
self.d = d
[でる]:
>>> Z(1,2,3,4)
<__main__.Z object at 0x10fcad950>
ただし、ベースクラスがnamedtuple
の場合:
from collections import namedtuple
X = namedtuple('X', 'a b c')
class Z(X):
def __init__(self, a, b, c, d):
super(Z, self).__init__(a, b, c)
self.d = d
[でる]:
>>> Z(1,2,3,4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __new__() takes exactly 4 arguments (5 given)
質問、名前付きタプルをPythonの基本クラスとして継承することは可能ですか?そうですか?
できますが、__new__
の前に暗黙的に呼び出される__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
しかし、d
は単なる独立した属性になります!
>>> list(z)
[1, 2, 3]
オリジナルの名前付きタプルにすべてのフィールドを含め、__new__
上記のschwobasegglが示唆するとおり。たとえば、入力値の一部を直接提供するのではなく計算するmaxの場合に対処するには、次のようにします。
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)
ちょうど2年後、まったく同じ問題でここに来ました。
個人的に@property
デコレータは、ここにうまく収まります。
from collections import namedtuple
class Base:
@property
def computed_value(self):
return self.a + self.b + self.c
# inherits from Base
class A(Base, namedtuple('A', 'a b c')):
pass
cls = A(1, 2, 3)
print(cls.computed_value)
# 6