Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheriting from a namedtuple base class

This question is asking the opposite of Inherit namedtuple from a base class in python , where the aim is to inherit a subclass from a namedtuple and not vice versa.

In normal inheritance, this works:

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 

[out]:

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

But if the baseclass is a 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 

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

The question, is it possible to inherit namedtuples as a base class in Python? Is so, how?

like image 643
alvas Avatar asked Feb 22 '17 08:02

alvas


People also ask

Can you subclass Namedtuple?

As namedtuples are a subclass of tuples, the fields can be accessed via the index or by the name of the field. The index value of a field is tied to the order during the declaration of the namedtuple. Consider the above Address example. You can access the street field by name or by using 0 as the index value.

Is Namedtuple a class?

NamedTuple . The class created from typing.

Can Namedtuple be pickled?

@Antimony: pickle handles namedtuple classes just fine; classes defined in a function local namespace not so much.

What type is a Namedtuple?

Python namedtuple is an immutable container type, whose values can be accessed with indexes and named attributes. It has functionality like tuples with additional features. A named tuple is created with the collections. namedtuple factory function.


2 Answers

You can, but you have to override __new__ which is called implicitly before __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 

But d will be just an independent attribute!

>>> list(z) [1, 2, 3] 
like image 95
user2390182 Avatar answered Oct 13 '22 02:10

user2390182


I think you can achieve what you want by including all of the fields in the original named tuple, then adjusting the number of arguments using __new__ as schwobaseggl suggests above. For instance, to address max's case, where some of the input values are to be calculated rather than supplied directly, the following works:

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) 
like image 39
TimH Avatar answered Oct 13 '22 01:10

TimH