Larry Hastings wrote:
I'd prefer a lightweight frozen dict, let's call it a "record" after one of the suggestions in this thread. That achieves symmetry:
                     mutable &     immutable &
                     heavyweight   lightweight
                   +--------------------------
        positional | list          tuple
        keyword    | dict          record
I knocked together a quick prototype of a "record" to show what I had in mind. Here goes:

------
import exceptions

class record(dict):
   __classname__ = "record"
   def __repr__(self):
       s = [self.__classname__, "("]
       comma = ""
       for name in self.__names__:
           s += (comma, name, "=", repr(self[name]))
           comma = ", "
       s += ")"
       return "".join(s)

   def __delitem__(self, name):
       raise exceptions.TypeError("object is read-only")

   def __setitem__(self, name, value):
       self.__delitem__(name)

   def __getattr__(self, name):
       if name in self:
           return self[name]
       return object.__getattr__(self, name)

   def __hasattr__(self, name):
       if name in self.__names__:
           return self[name]
       return object.__hasattr__(self, name)

   def __setattr__(self, name, value):
       # hack: allow setting __classname__ and __names__
       if name in ("__classname__", "__names__"):
           super(record, self).__setattr__(name, value)
       else:
           # a shortcut to throw our exception
           self.__delitem__(name)

   def __init__(self, **args):
       names = []
       for name, value in args.iteritems():
           names += name
           super(record, self).__setitem__(name, value)
       self.__names__ = tuple(names)

if __name__ == "__main__":
   r = record(a=1, b=2, c="3")
   print r
   print r.a
   print r.b
   print r.c
# this throws a TypeError
   # r.c = 123
   # r.d = 456
# the easy way to define a "subclass" of record
   def Point(x, y):
       return record(x = x, y = y)
# you can use hack-y features to make your "subclasses" more swell
   def Point(x, y):
       x = record(x = x, y = y)
       # a hack to print the name "Point" instead of "record"
       x.__classname__ = "Point"
       # a hack to impose an ordering on the repr() display
       x.__names__ = ("x", "y")
       return x
p = Point(3, 5)
   q = Point(2, y=5)
   r = Point(y=2, x=4)
   print p, q, r
# test pickling
   import pickle
   pikl = pickle.dumps(p)
   pp = pickle.loads(pikl)
   print pp
   print pp == p
# test that the output repr works to construct
   s = repr(p)
   print repr(s)
   peval = eval(s)
   print peval
   print p == peval
------

Yeah, I considered using __slots__, but that was gonna take too long.

Cheers,


/larry/
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to