A metaclass for creating structured records.
Record is a simple metaclass for creating classes whose instances are designed to hold a fixed number of named fields. It’s similar to collections.namedtuple in its operation, only it uses metaclasses rather than string formatting and exec.
>>> import math
>>> from urecord import Record
>>> class CartesianPoint(Record('x', 'y')):
... def to_polar(self):
... angle = math.atan2(self.y, self.x)
... radius = math.sqrt(self.x ** 2 + self.y ** 2)
... return PolarPoint(angle, radius)
>>> class PolarPoint(Record('angle', 'radius')):
... def to_cartesian(self):
... x = self.radius * math.cos(self.angle)
... y = self.radius * math.sin(self.angle)
... return CartesianPoint(x, y)
>>> p1 = CartesianPoint(3, 4)
>>> p1
CartesianPoint(x=3, y=4)
>>> p2 = p1.to_polar()
>>> p2
PolarPoint(angle=0.927..., radius=5.0)
>>> p2._replace(angle=0.25)
PolarPoint(angle=0.25, radius=5.0)
>>> p2._asdict()
{'radius': 5.0, 'angle': 0.927...}
For defining generic methods which operate over a class of records, you can subclass RecordInstance and pass this into Record:
>>> from urecord import RecordInstance
>>> class EuVector(RecordInstance):
... def magnitude(self):
... return math.sqrt(sum(cmp ** 2 for cmp in self))
>>> Vector2D = Record('x', 'y', name='Vector2D', instance=EuVector)
>>> Vector3D = Record('x', 'y', 'z', name='Vector3D', instance=EuVector)
>>> Vector2D(3, 4).magnitude()
5.0
>>> Vector3D(3, 4, 5).magnitude()
7.0710...