Python Module of the Week
The standard tuple uses numerical indexes to access its members.bob = ('Bob', 30, 'male') print 'Representation:', bob jane = ('Jane', 29, 'female') print '\nField by index:', jane print '\nFields by index:' for p in [ bob, jane ]: print '%s is a %d year old %s' % p
This makes tuples convenient containers for simple uses.$ python collections_tuple.py Representation: ('Bob', 30, 'male') Field by index: Jane Fields by index: Bob is a 30 year old male Jane is a 29 year old female
On the other hand, remembering which index should be used for each value can lead to errors, especially if the tuple has a lot of fields and is constructed far from where it is used. A namedtuple assigns names, as well as the numerical index, to each member.
namedtuple instances are just as memory efficient as regular tuples because they do not have per-instance dictionaries. Each kind of namedtuple is represented by its own class, created by using the namedtuple() factory function. The arguments are the name of the new class and a string containing the names of the elements.import collections Person = collections.namedtuple('Person', 'name age gender') print 'Type of Person:', type(Person) bob = Person(name='Bob', age=30, gender='male') print '\nRepresentation:', bob jane = Person(name='Jane', age=29, gender='female') print '\nField by name:', jane.name print '\nFields by index:' for p in [ bob, jane ]: print '%s is a %d year old %s' % p
As the example illustrates, it is possible to access the fields of the namedtuple by name using dotted notation (obj.attr) as well as using the positional indexes of standard tuples.$ python collections_namedtuple_person.py Type of Person: <type 'type'> Representation: Person(name='Bob', age=30, gender='male') Field by name: Jane Fields by index: Bob is a 30 year old male Jane is a 29 year old female
Invalid Field Names¶
As the field names are parsed, invalid values cause ValueError exceptions.import collections try: collections.namedtuple('Person', 'name class age gender') except ValueError, err: print err try: collections.namedtuple('Person', 'name age gender age') except ValueError, err: print err
Names are invalid if they are repeated or conflict with Python keywords.$ python collections_namedtuple_bad_fields.py Type names and field names cannot be a keyword: 'class' Encountered duplicate field name: 'age'
In situations where a namedtuple is being created based on values outside of the control of the programm (such as to represent the rows returned by a database query, where the schema is not known in advance), set the rename option to True so the fields are renamed.import collections with_class = collections.namedtuple('Person', 'name class age gender', rename=True) print with_class._fields two_ages = collections.namedtuple('Person', 'name age gender age', rename=True) print two_ages._fields
The field with name class becomes _1 and the duplicate age field is changed to _3.$ python collections_namedtuple_rename.py ('name', '_1', 'age', 'gender') ('name', 'age', 'gender', '_3')
Classes com criação dinâmica.