从 namedtuple 基础继承 class
Inheriting from a namedtuple base class
这个问题问的是 相反的问题,目的是从 namedtuple 继承 subclass 而不是相反。
在正常的继承中,这有效:
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>
但是如果基数class是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 中继承命名元组作为基础 class?是这样,怎么样?
你可以,但你必须覆盖 __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)
两年后,我带着完全相同的问题来到这里。
我个人认为 @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
由于namedtuple
是一个函数,与其严格地考虑继承,另一种方法是将它封装在一个新函数中。
然后问题就变成了:“我们如何构造一个具有默认属性 a, b, c
以及可选的一些附加属性的命名元组?”
def namedtuple_with_abc(name, props=[]):
added = props if type(props) == type([]) else props.split()
return namedtuple(name, ['a', 'b', 'c'] + added)
X = namedtuple_with_abc('X')
Z = namedtuple_with_abc('Z', 'd e')
>>> X(1, 2, 3)
X(a=1, b=2, c=3)
>>> Z(4, 5, 6, 7, 8)
Z(a=4, b=5, c=6, e=7, f=8)
这个问题问的是
在正常的继承中,这有效:
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>
但是如果基数class是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 中继承命名元组作为基础 class?是这样,怎么样?
你可以,但你必须覆盖 __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)
两年后,我带着完全相同的问题来到这里。
我个人认为 @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
由于namedtuple
是一个函数,与其严格地考虑继承,另一种方法是将它封装在一个新函数中。
然后问题就变成了:“我们如何构造一个具有默认属性 a, b, c
以及可选的一些附加属性的命名元组?”
def namedtuple_with_abc(name, props=[]):
added = props if type(props) == type([]) else props.split()
return namedtuple(name, ['a', 'b', 'c'] + added)
X = namedtuple_with_abc('X')
Z = namedtuple_with_abc('Z', 'd e')
>>> X(1, 2, 3)
X(a=1, b=2, c=3)
>>> Z(4, 5, 6, 7, 8)
Z(a=4, b=5, c=6, e=7, f=8)