tags:

views:

59

answers:

3

Hi my problem is that: I want to define a class in this way:

class List(Base):
    hp = Column(int,...)
    name = Column(str,...)

This class represents a list, I can define/modify/code the Base and the Column class. There's a way to know the order in which I defined the attributes hp/names? For example I want to define a method that can do this:

l = List()
l.show()
[(hp,16),(name,roger)] # in this order
A: 

I think you want something like this:

import inspect

class List(Base):
    hp = Column(int,...)
    name = Column(str,...)

    def show(self):
        public_bits = [(x, getattr(self, x)) for x in dir(self) if not x.startswith('__')]
        return [(x, y) for (x, y) in public_bits if not inspect.ismethod(y)]

Sadly, dir returns attributes in alphabetical order, so this may not exactly solve your problem.

Dominic Rodger
+2  A: 

Internally, attribute definitions are stored in a dictionary, which does not retain the order of the elements. You could probably change the attribute handling in the Base class, or you store the creation order, like this:

class Column:
    creation_counter = 0

    def __init__(self):
            self.creation_counter = Column.creation_counter
            Column.creation_counter += 1

class Base:
    def show(self):
        fields = [(name, (obj, obj.value)) for name, obj in self.__class__.__dict__.items() if isinstance(obj, Column)] 
        fields.sort(lambda (name1, (obj1, value1)), (name2, (obj2, value2)): cmp(obj1.creation_counter, obj2.creation_counter))
        return fields

Django stores the order of form fields in a similar way, albeit way more sophisticated. If you are interested, look at the source of Django forms and fields

Daniel Hepper
Thank you very much, this is what I was looking for!
pygabriel
Oops, I forgot to sort the elements, which was the point! I've modified the answer.
Daniel Hepper
A: 

Class and instance attributes are inherently unordered since they are stored in a dictionary.

There are a few options though:

1) classes defined with __slots__ do not use a dictionary, and the space for attributes are pre-allocated. I presume that the attributes are therefore ordered, so it should be possible in principle to get the data out. There are issues with using slots though, and it is not recommended.

2) add a list/tuple attribute to the class with the attribute order.

3) use a collection.namedtuple object to store the attributes. A namedtuple is a tuple where you can give names to the elements, and so is similar to a C struct. This will only work from Python 2.6 onwards. Since tuples are immutable you will not be able modify the attributes once created - this may or may not be a problem depending on the class.

Edit:

On reflection __slots__ will not work, since I think they only apply to instances and not class attributes.

Dave Kirby