I'm sure this has been done before, but it just struck my fancy, an example of Python's "emulating numeric types", inspired by the old Unix "units" utility, and the Frink language. The language reference for these features is somewhat unclear and I'll enter some sourceforge items. Maybe I'll write a calculator-with-units around it. If I were really industrious, I'd attempt a Frink-like interpreter, but don't hold your breath.
================================================================ try: set except NameError: from sets import Set as set # python 2.3 ... class Unit: def __init__(self, coef, dimensions): self.dimensions = dimensions self.coef = coef def __add__(self, other): if self.dimensions != other.dimensions: raise TypeError, ('dimension mismatch', self, other) return Unit(self.coef + other.coef, self.dimensions) def __sub__(self,other): return self + (-1.0) * other def __rmul__(self, x): return x*self def __rdiv__(self, x): return x/self def __mul__(self, other): pc = self.coef * other.coef sd, od = self.dimensions, other.dimensions basis = set(sd.keys()) | set(od.keys()) pa = [(d, sd.get(d,0)+od.get(d,0)) for d in basis] pd = dict([(d,a) for d,a in pa if a != 0]) return Unit(pc, pd) def __repr__(self): a = [repr(self.coef)] for d,c in self.dimensions.iteritems(): s = str(d) if c != 1: s += '^'+str(c) a.append(s) return '*'.join(a) def __div__(self, other): od = other.dimensions inv = Unit(1.0 / other.coef, dict([(d, -od[d]) for d in od])) return self * inv def __pow__(self, n): n = n.coef if self.dimensions and type(n) not in (int,long): raise TypeError, ('exponent must be integer', self,n) cn = self.coef ** n sd = self.dimensions return Unit(self.coef ** n, dict([(d,sd[d]*n) for d in sd])) def __coerce__(self, other): if isinstance(other, Unit): return self, other return self, Unit(other, {}) def __float__(self): if self.dimensions: raise TypeError, ('unit must be dimensionless for float cast', self) return float(self.coef) def __int__(self): return int(float(self)) def base_unit(name): return Unit(1.0, {name : 1}) meter = base_unit('m') second = base_unit('s') kg = base_unit('kg') coulomb = base_unit('coulomb') centimeter = meter / 100 inch = 2.54 * centimeter foot = ft = 12 * inch mile = 5280*foot minute=60*second hour=60*minute speed_limit = 55 * mile / hour furlong = mile / 8 day = 24 * hour fortnight = 14 * day # could include more units but you get the idea c = 186282*mile/second print 'speed of light =', c/(furlong/fortnight), 'furlongs per fortnight' # ... -- http://mail.python.org/mailman/listinfo/python-list