you probably shouldn't use them



Kurt Neufeld


  • what are they
  • why do you need them
  • why you almost never need them

But First!

      x = 1
      x = int(1)
      type(x) # <type 'int'>
      type(int) # ?

More But First!

      class MyClass(object): # always use object in python2
      c = MyClass()
      type(c) # <class '__main__.MyClass'>
      type(MyClass) # <type 'type'>

what happened to object?

A Bit More First!

      type(int) # <type 'type'>

      type(object) # <type 'type'>

brain starts exploding here

      type(type) # <type 'type'>

okay wtf?


just as c is an instance of MyClass

MyClass is an instance of type

It's turtles all the way down, until you get to type

type is an instance of type

Lets make a class!

      name = 'MyClass'
      bases = (object,)
      _dict = {'x':1}

      MyClass = type(name, bases, _dict)

      type(MyClass) # <type 'type'>

      MyClass.x       # 1
      c = MyClass()
      c.x             # 1
      c.x = 2
      MyClass.x       # 1
      c.x             # 2

We're already metaprogramming

So we used code to make a class

That's cool

I guess

Why would you want to do this?

Who here has used Django? SQLAlchemy?

The only reason I've come across to use metaclasses is model definition when you wan to talk to a database

There's probably several others

I bet Dave knows a few

Why would you want to do this?

When you want a new class with lots of functionality that almost identical to another class but it has nothing in common with it

same same but different

General Pattern

      class MetaClass(type):

        # this called once per derived class _definition_
        def __new__(meta_class, name, bases, attrs):
          new_class = type(name, bases, {})
          meta_class.do_things_to_class(new_class, attrs)
          return new_class

        # creates a new instance of derived class
        def __call__(cls, *args, **kw):
            obj = cls.__new__(cls, *args, **kw)
            obj.__init__(*args, **kw)
            return obj

      class MyClass(object):
          __metaclass__ = MetaClass

That doesn't look too bad...

Let's go spelunking!

Don't use them?

Well maybe you should use them, if you're positive you need them.

But it's hard to keep everything straight in your head, and a bug in your metaclass could appear as a bug in your real class.

Good resources


The End