Slight metaclass confusion

David Mertz mertz at gnosis.cx
Tue Sep 9 14:14:04 EDT 2003


ben at transversal.com (ben at transversal.com) wrote previously:
|"Metaclass Programming In Python, Parts 1 and 2"
|I get the fact that the instance of a metaclass is a class, but in
|this case I fail to see why the following does'nt work:

Read part 2 again.  It takes a while to sink in.

Your problem is that you aren't considering the MRO of Class:

  >>> class Meta(type):
  ...     def __str__(cls):     # Use 'return', not 'print'
  ...             return "I am " + repr(cls)
  ...     def foo(cls):
  ...             return "I am " + repr(cls)
  ...
  >>> Class = Meta("Fish", (), {})
  >>> Class.foo()
  "I am <class '__main__.Fish'>"

Class is an instance of Meta, just like you expect.  Calling the .foo()
method shows this.  But when you call a method, the method name is
checked in the -method resolution order- (before the metaclass is
checked):

  >>> Class.mro()
  [<class '__main__.Fish'>, <type 'object'>]

Fish doesn't define a method .__str__(), so Python looks in Fish's
parent, object.  Well, object -does- define, .__str__(), so your call
resolves to:

  >>> object.__str__()
  Traceback (most recent call last):
    File "<stdin>", line 1, in ?
  TypeError: descriptor '__str__' of 'object' object needs an argument

Of course, since object doesn't define a .foo(), resolution proceeds to
the metaclass.  If you want to get Class' metaclass method, you can let
Python do the magic for you:

  >>> str(Class)
  "I am <class '__main__.Fish'>"

Or if you want to be really explicit:

  >>> Class.__class__.__str__(Class)
  "I am <class '__main__.Fish'>"

Yours, David...

--
    _/_/_/ THIS MESSAGE WAS BROUGHT TO YOU BY: Postmodern Enterprises _/_/_/
   _/_/    ~~~~~~~~~~~~~~~~~~~~[mertz at gnosis.cx]~~~~~~~~~~~~~~~~~~~~~  _/_/
  _/_/  The opinions expressed here must be those of my employer...   _/_/
 _/_/_/_/_/_/_/_/_/_/ Surely you don't think that *I* believe them!  _/_/






More information about the Python-list mailing list