attribute assignment order in class definition
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)] # i开发者_开发百科n this order
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
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.
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.
精彩评论