Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying a namedtuple's constructor arguments via subclassing?

Tags:

I want to create a namedtuple which represents the individual flags in a short bitfield. I'm trying to subclass it so that I can unpack the bitfield before the tuple is created. However, my current attempt isn't working:

class Status(collections.namedtuple("Status", "started checking start_after_check checked error paused queued loaded")):     __slots__ = ()      def __new__(cls, status):         super(cls).__new__(cls, status & 1, status & 2, status & 4, status & 8, status & 16, status & 32, status & 64, status & 128) 

Now, my experience with super() is limited and my experience with __new__ is virtually non-existent, so I'm not quite sure what to make of the (to me) enigmatic error TypeError: super.__new__(Status): Status is not a subtype of super. Googling and digging into the docs haven't yielded anything enlightening.

Help?

like image 732
Ben Blank Avatar asked Aug 13 '10 05:08

Ben Blank


People also ask

Can Namedtuple have methods?

count() and . index() , namedtuple classes also provide three additional methods and two attributes. To prevent name conflicts with custom fields, the names of these attributes and methods start with an underscore. In this section, you'll learn about these methods and attributes and how they work.

What is the use of Namedtuple in Python?

The NamedTuple is another class, under the collections module. Like the dictionary type objects, it contains keys and that are mapped to some values. In this case we can access the elements using keys and indexes. To use it at first we need to import it the collections standard library module.

What is an advantage of Namedtuples over dictionaries?

Moreover, as namedtuple instances do not have per-instance dictionaries, they are lightweight and require no more memory than regular tuples. This makes them faster than dictionaries.

Where is Namedtuple defined?

namedtuple is in the collections library. typename: This is the name of the new tuple subclass. field_names: A sequence of names for each field.


2 Answers

You almost had it :-) There are just two little corrections:

  1. The new method needs a return statement
  2. The super call should have two arguments, cls and Status

The resulting code looks like this:

import collections  class Status(collections.namedtuple("Status", "started checking start_after_check checked error paused queued loaded")):     __slots__ = ()      def __new__(cls, status):         return super(cls, Status).__new__(cls, status & 1, status & 2, status & 4, status & 8, status & 16, status & 32, status & 64, status & 128) 

It runs cleanly, just like you had expected:

>>> print Status(47) Status(started=1, checking=2, start_after_check=4, checked=8, error=0, paused=32, queued=0, loaded=0) 
like image 190
Raymond Hettinger Avatar answered Oct 10 '22 08:10

Raymond Hettinger


I'd avoid super unless you're explicitly catering to multiple inheritance (hopefully not the case here;-). Just do something like...:

def __new__(cls, status):     return cls.__bases__[0].__new__(cls,                                     status & 1, status & 2, status & 4,                                     status & 8, status & 16, status & 32,                                     status & 64, status & 128) 
like image 20
Alex Martelli Avatar answered Oct 10 '22 08:10

Alex Martelli