Hooks, aspect-oriented programming, and design by contract
Alex Martelli
aleax at aleax.it
Wed Jan 23 10:17:01 EST 2002
<montanaro at tttech.com> wrote in message
news:15438.50149.145878.29445 at dynamic2.tttech1.ttt...
...
> This confuses me a bit. I assumed looking at your code that all that was
> necessary was that there be an object with the name "__metaclass__"
in-scope
> at class definition time. I was surprised that this slight modification
of
That might make more sense, perhaps, but it's not defined that way.
> In PEP 253 Guido said:
>
> - a class statement can contain a __metaclass__ declaration,
> specifying the metaclass to be used to create the new class
Sure.
> Which lead me to this modification:
>
> def makeaclassandafewinstances(meta=type):
> print "using", meta
> class justaclass:
> __metaclass__ = meta
> def __del__(self): print "destroying an instance"
> a = justaclass()
> b = justaclass()
>
> which does work. This, however:
Yes, it satisfies the PEP's clause.
> def makeaclassandafewinstances(__metaclass__=type):
> print "using", __metaclass__
> class justaclass:
> __metaclass__ = __metaclass__
> def __del__(self): print "destroying an instance"
> a = justaclass()
> b = justaclass()
>
> didn't, yielding a NameError for __metaclass__.
>
> Can you explain why your version works (__metaclass__ as a global), while
> the two versions with __metaclass__ as a local didn't and the version
using
> meta as a local did?
Because the PEP proceeds by explaining that, unless __metaclass__ is
defined in class scope, the next attempt is looking it
up in *global* scope -- it's never looked up in *local* scope. It's
function build_class in Python\ceval.c that implements this exact
specification: after trying and failing to find __metaclass__ in the
class being defined, or using the type its LEFTMOST base, for a
baseless class not directly defining __metaclass__ it falls down to:
PyObject *g = PyEval_GetGlobals();
if (g != NULL && PyDict_Check(g))
metaclass = PyDict_GetItemString(g, "__metaclass__");
i.e., globals-only, as per PEP.
I _think_ the idea is that this "last-ditch fallback" is to be
used only at module-scope -- perhaps even my approach, that of
_changing_ the global __metaclass__ dynamically, only works "by
accident", if the intention is not to have it dynamic at all.
Alex
More information about the Python-list
mailing list