Alex Rivera | Logout

In Python, how do I call the super class when it's a one-off namedtuple?

Asked 2010-11-01T18:12:38.713
15

So, I have a large number of message Payload classes for a serial API, each of which has a number of immutable fields, a parse method, and some methods which are shared. The way I'm structuring this is that each will inherit from a namedtuple for the field behaviours, and receive the common methods from a parent class. However, I'm having some difficulties with the constructors:

class Payload:
    def test(self):
        print("bar")

class DifferentialSpeed(Payload, namedtuple('DifferentialSpeed_', 
    'left_speed right_speed left_accel right_accel')):
    __slots__ = ()
    def __init__(self, **kwargs):
        super(DifferentialSpeed, self).__init__(**kwargs)
        # TODO: Field verification
        print("foo")

    @classmethod
    def parse(self, raw):
        # Dummy for now
        return self(left_speed = 0.0, right_speed = 0.1,
                    left_accel = 0.2, right_accel = 0.3)

    def __str__(self):
        return "Left Speed: %fm/s\nRight Speed: %fm/s\n"\
            "Left Acceleration: %fm/s^2\nRight Acceleration: %fm/s^2" % (
            self.left_speed, self.right_speed, self.left_accel, self.right_accel)


payload = DifferentialSpeed.parse('dummy')
print(payload)

This works, but I get the following warning:

DeprecationWarning: object.__init__() takes no parameters
  super(DifferentialSpeed, self).__init__(**kwargs)

If I remove **kwargs from the call, it still seems to work, but why? How are those arguments to the constructor getting passed through to the namedtuple? Is this guaranteed, or a random result of how the mro gets established?

If I wanted to stay away from super, and do it the old way, is there some way I can access the namedtuple to call its constructor? I'd rather not have to do this:

DifferentialSpeed_ = namedtuple('DifferentialSpeed_', 
    'left_speed right_speed left_accel right_accel')
class Different
Edit
Report

1 Answer

28

For starters, namedtuple(whatever) inherits from tuple, which is immutable, and immutable types don't bother with __init__, because by the time __init__ is called the object is already constructed. If you want to pass arguments to the namedtuple base class you'll have to override __new__ instead.

You can see the definition of the result of namedtuple() by passing in a verbose=true argument; I find it educational.

answered 2010-11-01T18:17:00.960

Your Answer