I want to define light-weight classes that are supposed to represent data structures. As is the case with many data structures, the order of the data is important. So if I go ahead and define this:
class User(DataStructure):
username = StringValue()
password = StringValue()
age = IntegerValue()
I am implying that this is a data structure where a string with the username comes first, followed by a string with the password, and finally the age of the user as an integer.
If you're familiar with Python, you'll know that the above class, User
, is an object inheriting from type
. It will, just like most other objects in Python, have a __dict__
. And here-in lies my problem. This __dict__
is a hash map, so the order of the class attributes in the __dict__
is in no way related to their order of definition.
Is there any way I can figure out the actual definition order? I'm asking here before I go with one of the less sane methods I can think of...
Oh and just to be clear, what I want is a way to get this out of the above definition: ['username', 'password', 'age']
Python 2.7 and 3.x define an OrderedDict
in the collections module. I believe it uses a linked list to maintain insertion order of its items. It adds iterable methods to the standard mutable mapping methods.
You could define a metaclass which uses an OrderedDict
rather than a standard unordered dict
as the namespace __dict__
for your data structures classes. If you give your metaclass a special __prepare__()
method you can do this. I haven't tried this but according to the docs it's possible:
From Python 3.1 Language Ref Section 3.3.3 Data Model - Customizing class creation:
If the metaclass has a __prepare__() attribute (usually implemented as a class
or static method), it is called before the class body is evaluated with the
name of the class and a tuple of its bases for arguments. It should return an
object that supports the mapping interface that will be used to store the
namespace of the class. The default is a plain dictionary. This could be used,
for example, to keep track of the order that class attributes are declared in
by returning an ordered dictionary.
Unfortunately the equivalent section 3.4.3 in the Python 2.7 Language Ref makes no mention of being able to substitute a class namespace dict and no mention of the __prepare__()
method. So this may only be possible in Python version 3.
This is something that is not well supported at all in Python. Django has employed metaclasses to deal with it. See this question: How does Django Know the Order to Render Form Fields?
(Summary: look at django.forms.forms.DeclarativeFieldsMetaclass
, django.forms.forms.get_declared_fields
and how creation_counter
is used in django.forms.fields.Field
.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With