Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate through class members in order of their declaration

Tags:

python

I got this problem writing a little GUI lib that maps classes to simple table views. Every class member of a certain type = column, and order of columns is important. But...

class Person(object):

    name = None
    date_of_birth = None
    nationality = None
    gender = None
    address = None
    comment = None


for member in Person.__dict__.iteritems():
    if not member[1]:
        print member[0]

output:

comment
date_of_birth
name
address
gender
nationality
...

ugh, the oder got all mixed up...desired output:

name
date_of_birth
nationality
gender
address
comment

Is there a way to do it without maintaining additional OrderedDict() of columns?

like image 573
AlexVhr Avatar asked Jul 02 '12 14:07

AlexVhr


1 Answers

It's possible in Python3, through the use of PEP3115 which allows you to override the dict type in the metaclass while the class is being constructed (eg. to use an OrderedDict which tracks the insertion order). Here's an implementation of this approach:

class OrderedMeta(type):
    @classmethod
    def __prepare__(metacls, name, bases): 
        return OrderedDict()

    def __new__(cls, name, bases, clsdict):
        c = type.__new__(cls, name, bases, clsdict)
        c._orderedKeys = clsdict.keys()
        return c

class Person(metaclass=OrderedMeta):
    name = None
    date_of_birth = None
    nationality = None
    gender = None
    address = None
    comment = None

for member in Person._orderedKeys:
    if not getattr(Person, member):
        print(member)

In Python2, it's a lot more tricky. It would be achievable with something fairly hacky like introspecting the source, and working out the definition order from the AST, but that's probably a lot more trouble than it's worth.

like image 146
Brian Avatar answered Oct 25 '22 19:10

Brian