Order in metaclass

Jeremy Bowers jerf at jerf.org
Tue Oct 12 16:46:32 EDT 2004


On Tue, 12 Oct 2004 15:37:22 -0400, 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?
> 
> Thx and regards,
> Nicolas

What order?

Yeah, they are listed in the source in a particular order, but there is
absolutely no difference between the six permutations of that order, in
theory or in fact, since the vars end up in a dict.

If you want a concept of "order", you're going to have do define one
yourself. What do you want to do, exactly?

I'm going to guess you're trying to get the vars out in order upon an
iteration, which may not be right but extends to other cases as well
fairly cleanly.

The easy solution is a list:

class MyClass(object):
    classData = [4, 5, 6]
    offsets = {'x': 0, 'y': 1, 'z':2}
    def getVarMaker(var):
        def getVar(self):
            return self.classData[self.offsets[var]]
        return getVar
    def setVarMaker(var):
        def setVar(self, value):
            self.classData[self.offsets[var]] = value
        return setVar
    x = property(getVarMaker('x'), setVarMaker('x'))
    y = property(getVarMaker('y'), setVarMaker('y'))
    z = property(getVarMaker('z'), setVarMaker('z'))
    def __iter__(self):
        for value in self.classData:
            yield value
    
A metaclass could take classData and offsets and make the access vars for
you.


--------
def getVarMaker(var):
    def getVar(self):
        return self.classData[self.offsets[var]]
    return getVar

def setVarMaker(var):
    def setVar(self, value):
        self.classData[self.offsets[var]] = value
    return setVar

class OrderedClassAttributes(type):
    def __init__(cls, name, bases, dict):
        super(OrderedClassAttributes, cls).__init__(name, bases, dict)
        for name in cls.offsets:
            setattr(cls, name, property(getVarMaker(name),
                setVarMaker(name)))

class MyClass(object):
    classData = [4, 5, 6]
    offsets = {'x': 0, 'y': 1, 'z':2}
    __metaclass__ = OrderedClassAttributes
    def __iter__(self):
        for value in self.classData:
            yield value
    
---------
(Assuming the above is copy/pasted into Python:)
>>> m = MyClass()
>>> m.x
4
>>> m.y
5
>>> m.z
6
>>> m.y = 33
>>> m.y
33
>>> list(m)
[4, 33, 6]
---------

Lightly tested but working as I designed.

Is that what you wanted? If not, feel free to ask more. There are
certainly other options but without more data, it is hard to know what you
need.

This is a pretty good metaclass use, I think.





More information about the Python-list mailing list