Dynamic Programming met Python. Deel 3: named tuples.

Wednesday 30 March 2011, 00:07:00 | python

Interessante voorbeelden van Dynamic Programming met Python.

  1. inleiding & de Fibonacci reeks; →Dynamic Programming met Python. Deel 1: fibonacci.
  2. rich comparison; →Dynamic Programming met Python. Deel 2: rich comparison.
  3. named tuples.

Tuples (immutable sequence) zijn handig maar niet handig genoeg: alle elementen kun je alleen met een indexnummer benaderen, en als er in de toekomst een verandering aan volgorde of aantal plaatsvindt, moet je moeilijk zoeken door je code om de indexering te fixen.

Vandaar collections.namedtuple: Een tuple waarbij de velden ook een naam hebben en niet alleen een numerieke index. En met een paar handige extra methods. Voorbeeld:

>>> import collections
>>> Vector=collections.namedtuple("Vector", "x y")
>>> v=Vector(4,7)
>>> v.x
4
>>> v.y
7
>>> v[0]
4
>>> v[1]
7
>>> v._asdict()
OrderedDict([('x', 4), ('y', 7)])

Het lijkt een beetje op een struct of enum uit andere programmeertalen maar het biedt meer (zoals gewoonlijk).

Meer interessante dingen (subclassing, csv-files lezen) met named tuples hieronder:

Een voorbeeld van subclassing: toevoegen van eigen methods/properties. Stel we hebben de Vector van hierboven, dan kun je b.v. een property hypot toevoegen (hypothenusa):

import math
class VectorExtra(Vector):
    @property
    def hypot(self):
        return math.sqrt(self.x*self.x + self.y*self.y)
    def __str__(self):
        return "Vector: x=%6.3f  y=%6.3f  hypot=%6.3f" % (self.x, self.y, self.hypot)

>>> v=VectorExtra(3,4)
>>> print v
Vector: x= 3.000  y= 4.000  hypot= 5.000
>>> v=VectorExtra(10,20)
>>> print v
Vector: x=10.000  y=20.000  hypot=22.361
>>> v.hypot
22.360679774997898
>>>

Een ander voorbeeld: het verwerken van csv-files. De meeste csv-files hebben op de eerste regel een header staan met de fieldnames erin. Die kunnen we prima gebruiken om de rest op een handige manier in te lezen:

# processcsv.py
import csv
from collections import namedtuple

with open("data.csv") as f:
    data=csv.reader(f)
    fields=next(data)
    Record=namedtuple("Record", fields)   # maak een named tuple met de juiste fields
    students=map(Record._make, data)      # lees alle regels in
    for student in students:
        print("{0} heeft score {1}".format(student.naam, student.score))

$ cat data.csv
naam,score
Henry,6.5
Suzanne,9.0
Frits,7.7

$ python processcsv.py
Henry heeft score 6.5
Suzanne heeft score 9.0
Frits heeft score 7.7