docs: def add_field(self, attrname, fn, default=None):
          """Computes a new attribute for each object in table, or replaces an
             existing attribute in each record with a computed value
             @param attrname: attribute to compute for each object
             @type attrname: string
             @param fn: function used to compute new attribute value, based on 
             other values in the object, as in::
                 
                 lambda ob : ob.commission_pct/100.0 * ob.gross_sales
                 
             @type fn: function(obj) returns value
             @param default: value to use if an exception is raised while trying
             to evaluate fn
             """
          # for rec in self:
          def _add_field_to_rec(rec_, fn_=fn, default_=default):
              try:
                  val = fn_(rec_)
              except Exception:
                  val = default_
              if isinstance(rec_, DataObject):
                  rec_.__dict__[attrname] = val
              else:
                  setattr(rec_, attrname, val)
          try:
              do_all(_add_field_to_rec(r) for r in self)
          except AttributeError:
              raise AttributeError("cannot add/modify attribute {!r} in table records".format(attrname))
          return self