[Python-Dev] Metaclass insanity - another use case
Phillip J. Eby
Tue, 05 Nov 2002 12:49:39 -0500
I was reading the "metaclass insanity" thread this morning about dotted
__name__ for nested classes, and I thought I should chime in that I've
actually *used* this technique. That is, I've had classes of the form:
And then regenerated 'inner' such that inner.__name__ == 'outer.inner' and
stored it in globals()['outer.inner']. This *does* work with existing
pickle code; in fact it worked as far back as Python 1.5.2!
As for *why* I had inner classes, the following might be a good example:
isRequired = 1
qualifiedName = 'Foundation.Core.ModelElement.isSpecification'
_XMINames = ('Foundation.Core.ModelElement.isSpecification',)
name = 'isSpecification'
referencedType = 'Boolean'
isNavigable = 0
isRequired = 1
_XMINames = ('Foundation.Core.ModelElement.stereotype',)
name = 'stereotype'
referencedType = 'Stereotype'
refTypeQN = 'Foundation.Core.ModelElement.stereotype'
referencedEnd = 'extendedElements'
This is a tiny excerpt from some automatically generated code which defines
the UML 1.3 metamodel as a set of Python classes. The nested classes
represent structural features of the defined outer class, and enforce
properties such as multiplicity, requiredness, etc., as you can see.
In an earlier version of this work, the inner classes had metaclasses whose
__get__ method instantiated the inner class, and placed an instance in the
outer object instance. That is, each ModelElement instance would have a
'stereotype' instance created on demand, which would manage the
'stereotype' property. And for this to be picklable, it was necessary for
the inner classes to be accessible by the pickle machinery -- hence my use
of qualified class names, as described above.
I will admit that I no longer use this approach for the inner classes; I
found a way to get by without ever instantiating them. The above code is
still valid, but the metaclasses used are different. So the pickling is
simpler and faster.
I'm not sure if this is really an argument for or against, but at least
it's actual usage. :)