[Python-Dev] Metaclass insanity - another use case
Guido van Rossum
guido@python.org
Tue, 05 Nov 2002 12:58:33 -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:
>
> class outer:
> class inner:
> ...
>
> 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!
OK. Setting __name__ to 'outer.inner' seems to be the best solution,
so I'll add that to my TODO list. [SF bug #633930]
> As for *why* I had inner classes, the following might be a good example:
>
>
> class ModelElement(Element):
>
> class isSpecification(model.Field):
> isRequired = 1
> qualifiedName = 'Foundation.Core.ModelElement.isSpecification'
> _XMINames = ('Foundation.Core.ModelElement.isSpecification',)
> name = 'isSpecification'
> referencedType = 'Boolean'
>
> class stereotype(model.Reference):
> 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. :)
And I think there's nothing wrong with it -- it's a different use of
classes, but makes sense; it's a good use of nested namespaces (as
opposed to nesting helper classes inside the main class which they
help).
--Guido van Rossum (home page: http://www.python.org/~guido/)