Metaclasses & docstrings in 2.2
Walter Dörwald
walter at livinglogic.de
Wed Jul 24 08:12:39 EDT 2002
Alex Martelli wrote:
> [...]
> ...would you please share your uses for metaclasses? I can use
> all the good examples I learn about -- it's hard to teach people
> how to use metaclasses without actual motivation, and the more
> real-life examples I can collect and quote, the more likely I
> can help people achieve that motivation!
The upcoming release of XIST (http://www.livinglogic.de/Python/xist/)
has several uses of metaclasses (see
http://www.livinglogic.de/viewcvs/index.cgi/LivingLogic/xist/_xist/xsc.py?rev=2.117.2.25&content-type=text/vnd.viewcvs-markup
for the source code.
The first example is a customized repr for nested classes,
that shows the class nesting:
class Base(object):
class __metaclass__(type):
def __new__(cls, name, bases, dict):
dict["__outerclass__"] = None
res = type.__new__(cls, name, bases, dict)
for (key, value) in dict.items():
if isinstance(value, type):
value.__outerclass__ = res
return res
def __repr__(self):
return "<class %s/%s at 0x%x>" % (self.__module__,
self.__fullname__(), id(self))
def __fullname__(cls):
name = cls.__name__
while 1:
cls = cls.__outerclass__
if cls is None:
return name
name = cls.__name__ + "." + name
__fullname__ = classmethod(__fullname__)
class foo(Base):
class bar(Base):
class baz(Base):
pass
print foo
print foo.bar
print foo.bar.baz
this prints:
<class __main__/foo at 0x817dfe4>
<class __main__/foo.bar at 0x815c50c>
<class __main__/foo.bar.baz at 0x8171034>
Another example is the following: A base class implements
a classmethod. Most subclasses that want to overwrite this
classmethod want to implement a version which returns a
constant value. Instead of defining:
def method(cls):
return constant
method = classmethod(method)
the subclass can simply say:
method = constant
and the metaclass will wrap this in an appropriate method.
The metaclass looks like this:
class __metaclass__(Base.__metaclass__):
def __new__(cls, name, bases, dict):
if dict.has_key("method"):
method_value = dict["method"]
if not isinstance(method_value, classmethod):
def method(cls):
return method_value
dict["method"] = classmethod(method)
return Base.__metaclass__.__new__(cls, name, bases, dict)
There are several more examples in the code, but they
are really application specific.
Bye,
Walter Dörwald
More information about the Python-list
mailing list