继承自namedtuple基类 - Python

alv*_*vas 20 python oop inheritance super namedtuple

这个问题与来自python中的基类Inherit 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
Run Code Online (Sandbox Code Playgroud)

[OUT]:

>>> Z(1,2,3,4)
<__main__.Z object at 0x10fcad950>
Run Code Online (Sandbox Code Playgroud)

但如果基类是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
Run Code Online (Sandbox Code Playgroud)

[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)
Run Code Online (Sandbox Code Playgroud)

问题是,是否可以在Python中继承namedtuples作为基类?是这样,怎么样?

sch*_*ggl 25

你可以,但你必须覆盖__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
Run Code Online (Sandbox Code Playgroud)

但这d只是一个独立的属性!

>>> list(z)
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

  • 从`namedtuple` 继承是一种反模式,还是如果我只需要一个轿跑车额外的参数,我想与其他参数分开,这是一种合理的方法吗?(具体来说,我希望它们在 `__init__` 中计算而不是在用户代码中分配。) (4认同)

小智 8

我认为你可以通过包含原始命名元组中的所有字段来实现你想要的,然后使用__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)
Run Code Online (Sandbox Code Playgroud)


Jan*_*Jan 5

两年后,我带着完全相同的问题来到这里。
我个人认为@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
Run Code Online (Sandbox Code Playgroud)