Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

structs in python

1 view
Skip to first unread message

Christos TZOTZIOY

unread,
Dec 27, 2002, 3:52:46 AM12/27/02
to
On Mon, 8 Jul 2002 08:09:20 +0200, rumours say that Gerhard Häring
<gerhard...@gmx.de> might have written:

>* Christopher A. Craig <list-...@ccraig.org> [2002-07-08 01:22 -0400]:
>> "Kevin O'Connor" <ke...@koconnor.net> writes:
>>
>> > What if a syntax like the following were permitted:
>> > >>> p = ( .x = 10, .y = 11, .color = 'blue')
>> > >>> print p.x
>> > 10
>> > >>>
>>
[snip suggesting using a dict]
>
>I prefer tiny data-only classes. These can be used exactly like a a
>struct.

I know this will be too late (limited time in the last few months made
me skip group browsing...), and perhaps Alex Martelli's solution is more
generic, but the solution I have come to for my needs might be useful to
others too.
I sometimes need lots of struct-like tuples (immutable structs of
various "types" with named access to their members), and here follows
the module I named "TupleStruct.py", defining a class-factory named
TupleStructType. Check at the bottom for an example usage.

"""TupleStructType: a metaclass to create classes based on tuple
with named access to the tuple members"""
# (c) tz...@sil-tec.gr 20020914
# License: Public Domain
__version__= (1, 0, 0)
import sys
if sys.hexversion<0x02030000:
from tzot.future import enumerate # simulate 2.3 enumerate
# to simulate enumerate for python <2.3, use the following
# function:
#def enumerate(seq):
# _index= 0
# for _itm in seq:
# yield (_index, _itm)
# _index+= 1


class TupleStructType(type):
"""Create a tuple derived class with named members"""

def __new__(cls, members):
"""Create a new class with the members specified as space
separated words in a string"""
member_list= members.split()
attributes= {}

def new_cls_new(new_cls, *data):
return tuple.__new__(new_cls, data)
attributes['__new__']= new_cls_new
attributes['__slots__']= () # important, so the new class won't
have a dict

# factory for the property get functions
def property_factory(index):
def property_get(self):
try:
value= self[index]
except IndexError:
value= None
return value
return property_get

# getstate, setstate for pickling
def my_getstate(self):
return tuple(self)
attributes['__getstate__']= my_getstate
def my_setstate(self, data):
self= self.__class__(*data)
attributes['__setstate__']= my_setstate

# create the property get functions
for index, member in enumerate(member_list):
attributes[member]= property(property_factory(index))
attributes['__doc__']="TupleStruct(%s)" % ','.join(member_list)

cls_name= "TplStr_" + '_'.join(member_list)
new_cls= type.__new__(cls, cls_name, (tuple,), attributes)
globals()[cls_name]= new_cls # add the name to the module for
pickle use
return new_cls

if __name__=="__main__":
Person= TupleStructType("name city age") # Person is a class now
person= Person("Chris", "Athens", 30)
tpl= ("Chris", "Athens", 30)
person2= Person(*tpl)
if person[0]!=person.name or person[1]!=person.city \
or person[2]!=person.age:
print "named access failed"
if person!=tpl:
print "comparison to tuple failed"
if person!=person2:
print "comparison to other person failed"
person0= Person("Lena")
if person0.age is not None:
print "missing members are not None"
print person0.__class__
print dir(person0)


--
TZOTZIOY, I speak England very best,
Real email address: 'dHpvdEBzaWwtdGVjLmdy\n'.decode('base64')

0 new messages