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