text: def demo():
      # The definition of measure classes is straightforward, for example:
      class Length(object):
          __metaclass__ = MeasureType
          DEFAULT_UNIT = "m"
          _TO_DEFAULT = { "mm":0.001, "cm":0.01, "km":1000,
                          "in":0.0254, "ft":0.3048, "yd":0.9144, "mi":1609.34
                        }
      
      l1 = Length(12.3,'cm')
      l2 = Length(50,'mm')
      Length.setDefaultUnit("in")
      print l1+l2             # "6.811024 in"
      print 3*l2.value("m")   # "0.15"
      print l1>l2             # "True"
  
      # Measures with arbitrary unit conversion functions, like temperature,
      # are also supported:
      class Temperature(object):
          __metaclass__ = MeasureType
          DEFAULT_UNIT = "Celsius"
          _TO_DEFAULT =   { "Fahrenheit" : lambda tf: 5.0/9.0 * (tf-32) }
          _FROM_DEFAULT = { "Fahrenheit" : lambda tc: 9.0/5.0 * tc + 32 }
  
  #todo:
  # - support for unit prefixes (e.g. "c" for 10^-2, "k" for 10^3", etc.);
  #   thus "cm", "km", etc. won't have to be specified for Length
  # - unit name aliases (e.g. "kilometers","km")
  # - compound measures: 
  #   a. Compound measure definition (e.g. Velocity)
  #   b. Modify *,/ to be allowed between any Measure instances (e.g. Length/Duration)
  #   c. Combine a and b (?)
  # - thorough unit testing
  
  __author__ = "George Sakkis"
  
  class MeasureType(type):
      '''Metaclass for supporting unit-safe measure objects. Classes generated with 
        this as metaclass (e.g. Length, Area, Temperature, etc.) must define the 
        following class-scope variables:
        1.  DEFAULT_UNIT (a string), and 
        2a. either _TO_DEFAULT, a dictionary that maps each other unit to
            - either a constant number, which is interpreted as the ratio of the
              unit to the DEFAULT_UNIT
            - or a function, for more complicate conversions from the unit to
              DEFAULT_UNIT (e.g. from Celsius to Fahrenheit).
         2b. or _FROM_DEFAULT. Inverse of _TO_DEFAULT, maps each unit
              (other than the DEFAULT_UNIT) to the function that
              returns the measure in this unit, given the DEFAULT_UNIT
              (e.g. from Fahrenheit to Celsius).
        If there is at least one function present, both _TO_DEFAULT and _FROM_DEFAULT
        have to be given (so that both the function and its inverse are defined).'''
      
      def __new__(cls,classname,bases,classdict):
          defUnit = classdict["DEFAULT_UNIT"]
          toDefault = classdict.get("_TO_DEFAULT") or {}
          fromDefault = classdict.get("_FROM_DEFAULT") or {}
          units = uniq([defUnit] + toDefault.keys() + fromDefault.keys())
          restUnits = units[1:]
          # form convertion matrix
          conversion_matrix = {}
          # 1. non-default unit -> default unit
          for unit in restUnits:
              try: conversion_matrix[(unit,defUnit)] = toDefault[unit]
              except KeyError:
                  try: conversion_matrix[(unit,defUnit)] = 1.0 / fromDefault[unit]
                  except (KeyError,TypeError): raise LookupError, "Cannot convert %s to %s" % (unit,defUnit)
          # 2. default unit -> non-default unit
          for unit in restUnits:
              # check if toDefault[unit] is number
              try: conversion_matrix[(defUnit,unit)] = fromDefault[unit]
              except KeyError:
                  try: conversion_matrix[(defUnit,unit)] = 1.0 / toDefault[unit]
                  except (KeyError,TypeError): raise LookupError, "Cannot convert %s to %s" % (defUnit,unit)
          # 3. non-default unit -> non-default unit
          for fromUnit in restUnits:
              for toUnit in restUnits:
                  if fromUnit != toUnit:
                      try: conversion_matrix[(fromUnit,toUnit)] = conversion_matrix[(fromUnit,defUnit)] \
                                                                 * conversion_matrix[(defUnit,toUnit)]
                      except TypeError: 
                          conversion_matrix[(fromUnit,toUnit)] = \
                                  lambda value: conversion_matrix[(defUnit,toUnit)](
                                                  conversion_matrix[(fromUnit,defUnit)](value))
          ## print conversion_matrix
          # 4. convert all constants c to functions lambda x: c*x
          for (k,v) in conversion_matrix.iteritems():
              try: conversion_matrix[k] = lambda x,i=float(v): x*i
              except (TypeError,ValueError): pass
          # update classdict                                        
          assert "_CONVERT_UNITS" not in classdict
          classdict["_CONVERT_UNITS"] = conversion_matrix
          classdict["_UNITS"] = units
          if "_TO_DEFAULT" in classdict: del classdict["_TO_DEFAULT"]
          if "_FROM_DEFAULT" in classdict: del classdict["_FROM_DEFAULT"]
          # set Measure to be base a class of cls
          bases = tuple(uniq((MeasureType.Measure,) + bases))
          return type.__new__(cls,classname,bases,classdict)
  
      class Measure(object):
          '''The superclass of every Measure class. Concrete measure classes
             don't have to specify explicitly this class as their superclass; 
             it is added implicitly by the MeasureType metaclass.'''
          
          __slots__  = "_value", "_unit"
          
          def setDefaultUnit(cls,unit):
              if unit != cls.DEFAULT_UNIT:
                  cls.__verifyUnit(unit)
                  cls.DEFAULT_UNIT = unit
          setDefaultUnit = classmethod(setDefaultUnit)
  
          def value(self, unit=None):
              if unit == None: unit = self.__class__.DEFAULT_UNIT
              self.__verifyUnit(unit)
              return self.__convert(self._value, self._unit, unit)
  
          def __init__(self, value, unit=None):
              if unit == None: unit = self.__class__.DEFAULT_UNIT
              self.__verifyUnit(unit)
              self._unit = self.__class__.DEFAULT_UNIT
              self._value = self.__convert(value, unit, self._unit)
                          
          def __str__(self,unit=None):
              if unit == None: unit = self.__class__.DEFAULT_UNIT
              return "%f %s" % (self.value(unit), unit)
          
          def __abs__(self): return self.__class__(abs(self._value), self._unit)
          
          def __neg__(self): return self.__class__(-self._value, self._unit)
      
          def __cmp__(self,other):
              try: return cmp(self._value, self.__coerce(other))
              except ValueError: return cmp(id(self),id(other))
  
          def __add__(self,other):
              try: return self.__class__(self._value + self.__coerce(other), self._unit)
              except ValueError: raise ValueError, "can only add '%s' (not '%s') to '%s'" \
                                                  % (self.__class__.__name__,
                                                     other.__class__.__name__,
                                                     self.__class__.__name__)
          def __sub__(self,other):
              try: return self.__class__(self._value - self.__coerce(other), self._unit)
              except ValueError: raise ValueError, "can only subtract '%s' (not '%s') from '%s'" \
                                                  % (self.__class__.__name__,
                                                     other.__class__.__name__,
                                                     self.__class__.__name__)
          def __iadd__(self,other):
              try: self._value += self.__coerce(other)
              except ValueError: raise ValueError, "can only increment '%s' (not '%s') by '%s'" \
                                                  % (self.__class__.__name__,
                                                     other.__class__.__name__,
                                                     self.__class__.__name__)
      
          def __isub__(self,other):
              try: self._value -= self.__coerce(other)
              except ValueError: raise ValueError, "can only decrement '%s' (not '%s') by '%s'" \
                                                  % (self.__class__.__name__,
                                                     other.__class__.__name__,
                                                     self.__class__.__name__)
      
          def __mul__(self,other):
              try: return self.__class__(self._value * float(other), self._unit)
              except TypeError: raise ValueError, "can only multiply '%s' (not '%s') by a number" \
                                                  % (self.__class__.__name__, other.__class__.__name__)
              
          __rmul__ = __mul__        
                          
          def __div__(self,other):
              try: return self.__class__(self._value / float(other), self._unit)
              except TypeError: raise ValueError, "can only divide '%s' (not '%s') by a number" \
                                                  % (self.__class__.__name__, other.__class__.__name__)
          def __imul__(self,other):
              try: self._value *= float(other)
              except TypeError: raise ValueError, "can only multiply '%s' (not '%s') by a number" \
                                                  % (self.__class__.__name__, other.__class__.__name__)
      
          def __idiv__(self,other):
              try: self._value /= float(other)
              except TypeError: raise ValueError, "can only divide '%s' (not '%s') by a number" \
                                                  % (self.__class__.__name__, other.__class__.__name__)
          
          def __pow__(self,other):
              try: return self.__class__(self._value ** float(other), self._unit)
              except TypeError: raise ValueError, "can only raise '%s' to a number (not '%s')" \
                                                  % (self.__class__.__name__, other.__class__.__name__)
              
          def __ipow__(self,other):
              try: self._value **= float(other)
              except TypeError: raise ValueError, "can only raise '%s' to a number (not '%s')" \
                                                  % (self.__class__.__name__, other.__class__.__name__)
              
          ################################## 'private' Methods ##################################
      
          def __convert(cls, value, fromUnit, toUnit):
              if fromUnit == toUnit: return value
              else: return cls._CONVERT_UNITS[(fromUnit,toUnit)](value)
          __convert = classmethod(__convert)
          
          def __verifyUnit(cls,unit):
              if unit not in cls._UNITS:
                  raise ValueError, "'%s' is not a recognized %s unit (pick one from %s)" % \
                                    (unit, cls.__name__, ', '.join(["'%s'" % u for u in cls._UNITS]))
          __verifyUnit = classmethod(__verifyUnit)
          
          def __coerce(self,other):
              if type(self) != type(other) or not isinstance(self,MeasureType.Measure):
                  raise ValueError
              return self.__convert(other._value,other._unit,self._unit)
  
  
  def uniq(sequence):
      '''Removes the duplicates from the given sequence, preserving the order
         of the remaining elements.'''
      dict = {}
      try:
          return [dict.setdefault(i,i) for i in sequence if i not in dict]
      except TypeError:   # unhashable item(s)
          return [dict.setdefault(repr(i),i) for i in sequence if repr(i) not in dict]
  
  if __name__ == '__main__': demo()
  