This is probably a good practice anyway. I'm curious now how I can test and see if I'm taking advantage of this or not. I wonder if using the attrs module will also make use of this new feature.
This is probably a good practice anyway. I'm curious now how I can test and see if I'm taking advantage of this or not. I wonder if using the attrs module will also make use of this new feature.
* __repr__ comes for free.
* converting all members to a list or dict comes for free.
* converting a list or dict TO a namedtuple comes for free.
* more restrictive in what you can do with data structures inside the namedtuple - may lead to a cleaner design where you think about pulling apart the data into multiple tuples at an earlier point in the prototype phase.
* You by design won't make functions into instance methods that depend on multiple data tuples.
* Need to extend a function to deal with different types of tuples? You now don't need to refactor an instance method into a first class function, instead just dispatch and be done.
* Inheritance can be solved with the above method as well. This may actually be more maintainable than class based inheritance, since you see all the logic for a specific function explicitely (or explicitely dispatched) in one place.
The only reason I can think of to still use a class: If you can heavily profit from inheritance or if you need to program against an "interface" like dict- or listlike behavior or comparison operators.
I think organizing / refactoring a bunch of named tuples would be a mess. In one code base I maintain I switched a bunch of namedtuples to attrs classes and the code instantly became more readable / maintainable.
The downside to the namedtuple is that it's a tuple and can be unpacked as one.
for x, y in points: print x, y
# vs.
for p in points: print p.x, p.y
# ... now go and add a z to the point class and see what happens to your code.
Adding an attribute doesn't impact any code that doesn't use the attribute.
> from collections import namedtuple
> Point = namedtuple('Point', ['x', 'y'])
> points = [Point(3,4), Point(5,2)]
> for p in points:
> print(p.x, p.y)