2

From this answer to "what is a metaclass?" I got this:

You write class Foo(object) first, but the class object Foo is not created in memory yet.

Python will look for metaclass in the class definition. If it finds it, it will use it to create the object class Foo. If it doesn't, it will use type to create the class.

Having tested it, it seems that the attributes of the class are instantiated before the constructor of the class is run. What am I misunderstanding?

Test code:

class meta(type):

    def __init__(cls, name, bases, dic):
        type.__init__(cls, name, bases, dic)

        print hasattr(cls, "a")
        cls.a = "1"


class A(object):
    a = "a"
    __metaclass__ = meta


class B(object):
    __metaclass__ = meta


class C(object):
    __metaclass__ = meta
    a = "a"


print A.a
print B.a
print C.a

Output:

True
False
True
1
1
1
Community
  • 1
  • 1
cammil
  • 9,499
  • 15
  • 55
  • 89

1 Answers1

4

The class body is run before the class is constructed, yes.

The body of the class provides a temporary namespace, and all local names in that namespace are given as a dictionary to construct the class object, together with the base classes and a name for the class.

You can do this with the type() constructor too:

>>> Foo = type('Foo', (), {'a': 1})
>>> Foo.a
1

The class body is basically executed as a function, with the local namespace of that function being used to create the class attributes, the 3rd argument to type() above.

In python 3 you have a little more influence on that process with the __prepare__ hook on a metaclass. __prepare__ should be a class method that returns a initial namespace for the class body; use it to inject extra names into the generated class body before the class body is executed:

class MyMeta(type):
   @classmethod
   def __prepare__(mcl, name, bases):
       return {'a': 1}
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343