[Python-Dev] A "record" type (was Re: Py2.6 ideas)
Larry Hastings
larry at hastings.org
Tue Feb 20 20:16:13 CET 2007
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/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/python-dev/attachments/20070220/33b6b9a9/attachment.html
More information about the Python-Dev
mailing list