How to read class attributes in the same order as declared? How to read class attributes in the same order as declared? python python

How to read class attributes in the same order as declared?


In the current version of Python, the class ordering is preserved. See PEP520 for details.

In older versions of the language (3.5 and below, but not 2.x), you can provide a metaclass which uses an OrderedDict for the class namespace.

import collections class OrderedClassMembers(type):    @classmethod    def __prepare__(self, name, bases):        return collections.OrderedDict()    def __new__(self, name, bases, classdict):        classdict['__ordered__'] = [key for key in classdict.keys()                if key not in ('__module__', '__qualname__')]        return type.__new__(self, name, bases, classdict)class Something(metaclass=OrderedClassMembers):    A_CONSTANT = 1    def first(self):        ...    def second(self):        ...print(Something.__ordered__)# ['A_CONSTANT', 'first', 'second']

This approach doesn't help you with existing classes, however, where you'll need to use introspection.


Here is the workaround I juste developped :

import inspectclass Column(object):    creation_counter = 0    def __init__(self):        self.creation_order = Column.creation_counter        Column.creation_counter+=1class ListingMeta(type):    def __new__(meta, classname, bases, classDict):        cls = type.__new__(meta, classname, bases, classDict)        cls.columns = sorted(inspect.getmembers(cls,lambda o:isinstance(o,Column)),key=lambda i:i[1].creation_order)         cls.nb_columns = len(cls.columns)        return clsclass Listing(object):    __metaclass__ = ListingMeta    mycol2 = Column()    mycol3 = Column()    zut = Column()    cool = Column()    menfin = Column()    a = Column()for colname,col in Listing.columns:    print colname,'=>',col.creation_order


For python 3.6, this has become the default behavior. See PEP520: https://www.python.org/dev/peps/pep-0520/

class OrderPreserved:    a = 1    b = 2    def meth(self): passprint(list(OrderPreserved.__dict__.keys()))# ['__module__', 'a', 'b', 'meth', '__dict__', '__weakref__', '__doc__']