Structures

Arnaud Delobelle arnodel at googlemail.com
Tue Nov 4 08:35:58 EST 2008


Marc 'BlackJack' Rintsch <bj_666 at gmx.net> writes:

> On Mon, 03 Nov 2008 23:32:25 +0000, Paulo J. Matos wrote:
>
>> What's then the reason for adding named tuples if they are not
>> mutable...???
>
> Names are more descriptive than "magic numbers" as indices.  See for 
> example the "named tuple" returned by `os.stat()`.
>
> Ciao,
> 	Marc 'BlackJack' Rintsch

I'm reminded of a 'struct' decorator I made some time ago:

def struct(f):
    classname = f.__name__
    prop_names = f.func_code.co_varnames[:f.func_code.co_argcount]
    def _new(cls, *args, **kwargs):
        return tuple.__new__(cls, f(*args, **kwargs))
    def _repr(self):
        return '%s%s' % (type(self).__name__, tuple(self))
    def prop(i):
        return property(lambda self: self[i])
    attrs = { '__slots__': (), '__new__': _new, '__repr__': _repr }
    attrs.update((name, prop(i)) for i, name in enumerate(prop_names))
    return type(classname, (tuple,), attrs)


The advantage over namedtuple is that you don't have to repeat the name
of the structure and you can easily define default values.  The drawback
is that it involved some mild hackery (It won't work as is in Python 3
as f.func_code changed to f.__code__).  It worked like this:

>>> @struct
... def Point(x=0, y=0): return float(x), float(y)
...
>>> p, q = Point(2, 7), Point(y=3)
>>> p, q
(Point(2.0, 7.0), Point(0.0, 3.0))
>>> x, y = p
>>> x, y
(2.0, 7.0)
>>> p.x + p.y
9.0
>>> p.x = 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>> isinstance(p, tuple)
True

It's immutable but it would be easy to make it mutable by making it
inherit from list instead of tuple.

You could even have some processing:

>>> @struct
... def Interval(start, end, size=None):
...     size = end - start
...     return start, end, size
... 
>>> I = Interval(2.5, 6.0)
>>> I.start, I.end, I.size
(2.5, 6.0, 3.5)

-- 
Arnaud



More information about the Python-list mailing list