Frage

Running this (Python 3.3.1):

from collections import OrderedDict


class MyType(type):
    @classmethod
    def __prepare__(*args):
        return OrderedDict()


class MyClass2(metaclass=MyType):

    attr1 = 1
    attr2 = 2
    attr3 = 3
    attr4 = 4
    attr5 = 5

    def __init__(self):
        self.attr6 = 6

    def func(self):
        pass



print(MyClass2.__dict__.items())

i am getting:

dict_items([('__weakref__', <attribute '__weakref__' of 'MyClass2' objects>), ('__dict__', <attribute '__dict__' of 'MyClass2' objects>), ('__init__', <function MyClass2.__init__ at 0x7f08a106dc20>), ('__doc__', None), ('attr4', 4), ('attr5', 5), ('attr2', 2), ('attr3', 3), ('attr1', 1), ('func', <function MyClass2.func at 0x7f089f995c20>), ('__module__', '__main__')])

The class attributes are not sorted by their definition order.

What am i doing wrong to use OrderedDict as class __dict__?

War es hilfreich?

Lösung

The __prepare__ method in a mataclass allows you to provide your own custom object in place of the dict used for class initialisation. However you cannot change the type of object actually used by the class, that will be an instance of an internal type known as mappingproxy and is unordered. If you want to preserve the order in which the attributes where defined you must store that separately:

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

         def __new__(cls, name, bases, classdict):
            result = type.__new__(cls, name, bases, classdict)
            result.member_names = list(classdict.keys())
            return result


class MyClass2(metaclass=OrderedClass):

    attr1 = 1
    attr2 = 2
    attr3 = 3
    attr4 = 4
    attr5 = 5

    def __init__(self):
        self.attr6 = 6

    def func(self):
        pass

>>> MyClass2.member_names
['__module__', '__qualname__', 'attr1', 'attr2', 'attr3', 'attr4', 'attr5', '__init__', 'func']
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top