Order in metaclass

Peter Otten __peter__ at web.de
Wed Oct 13 03:04:03 EDT 2004


Nicolas Fleury wrote:

> In the following example:
> 
> class MyMetaclass(type): pass
> class MyBaseType(object): __metaclass__ = MyMetaclass
> class MyType(MyBaseType):
>      x = 4
>      y = 5
>      z = 6
> 
> Is there any way to modify MyMetaclass to keep the order of x,y,z
> somewhere?

If you want to record the order of these definitions, you need to pass a
custom dictionary that keeps track of assignments in the class generation
code (basically a normal python function comprising the class suite).
Unfortunately that dictionary - which you see later as the classdict
parameter of the metaclass __new__() method - is always a dict created in C,
as was recently discussed on c.l.py (sorry, but all keywords I remember are
'metaclass' and 'martelli' - not very selective :-). Below is my (clumsy)
attempt for a workaround:

import itertools

class OrderedValue(object):
    newIndex = itertools.count(1).next
    def __init__(self, value):
        self.value = value
        self.index = self.newIndex()
        
class Meta(type):
    def __new__(mcl, name, bases, classdict):
        assert "ordered_names" not in classdict
        
        values = []
        for (n, v) in classdict.iteritems():
            try:
                v, i = v.value, v.index
            except AttributeError:
                pass
            else:
                values.append((i, n, v))
        values.sort()

        ordered_names = []
        for (i, n, v) in values:
            ordered_names.append(n)
            classdict[n] = v
        classdict["ordered_names"] = ordered_names
        
        return type.__new__(mcl, name, bases, classdict)
        
                
class Base:
    __metaclass__ = Meta
    
class Demo(Base):
    alpha = 0
    beta = OrderedValue(1)
    gamma = OrderedValue(17)
    delta = OrderedValue(3)
    
print Demo.ordered_names        
print Demo.alpha, Demo.beta


Peter




More information about the Python-list mailing list