Hooks, aspect-oriented programming, and design by contract
montanaro at tttech.com
montanaro at tttech.com
Wed Jan 23 09:08:37 EST 2002
Alex> One simple (maybe even silly) example: I can write a metaclass
Alex> that does substantially nothing different from builtin type (the
Alex> normal metaclass of all except classic classes) EXCEPT emit a
Alex> message upon each instantiation:
Alex> import types
Alex> class mymeta(type):
Alex> def __call__(self, *arg, **kw):
Alex> print "Creating instance of", self.__name__
Alex> return type.__call__(self, *arg, **kw)
Alex> def makeaclassandafewinstances():
Alex> class justaclass:
Alex> def __del__(self): print "destroying an instance"
Alex> a = justaclass()
Alex> b = justaclass()
Alex> __metaclass__ = type
Alex> makeaclassandafewinstances()
Alex> __metaclass__ = mymeta
Alex> makeaclassandafewinstances()
Alex,
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
your example doesn't work:
import types
class mymeta(type):
def __call__(self, *arg, **kw):
print "Creating instance of", self.__name__
return type.__call__(self, *arg, **kw)
def makeaclassandafewinstances(__metaclass__=type):
print "using", __metaclass__
class justaclass:
def __del__(self): print "destroying an instance"
a = justaclass()
b = justaclass()
makeaclassandafewinstances(type)
makeaclassandafewinstances(mymeta)
Running it, I get
using <type 'type'>
destroying an instance
destroying an instance
using <class '__main__.mymeta'>
destroying an instance
destroying an instance
In PEP 253 Guido said:
- a class statement can contain a __metaclass__ declaration,
specifying the metaclass to be used to create the new class
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:
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?
Thx,
--
Skip Montanaro (skip at pobox.com - http://www.mojam.com/)
More information about the Python-list
mailing list