views:

198

answers:

3

I've always set up metaclasses something like this:

class SomeMetaClass(type):
    def __new__(cls, name, bases, dict):
        #do stuff here

But I just came across a metaclass that was defined like this:

class SomeMetaClass(type):
    def __init__(self, name, bases, dict):
        #do stuff here

Is there any reason to prefer one over the other?

Update: Bear in mind that I'm asking about using __new__ and __init__ in a metaclass. I already understand the difference between them in another class. But in a metaclass, I can't use __new__ to implement caching because __new__ is only called upon class creation in a metaclass.

+1  A: 

You can implement caching. Person("Jack") always returns a new object in the second example while you can lookup an existing instance in the first example with __new__ (or not return anything if you want).

Otto Allmendinger
+7  A: 

If you want to alter the attributes dict before the class is created, or change the bases tuple, you have to use __new__. By the time __init__ sees the arguments, the class object already exists. Also, you have to use __new__ if you want to return something other than a newly created class of the type in question.

On the other hand, by the time __init__ runs, the class does exist. Thus, you can do things like give a reference to the just-created class to one of its member objects.

Edit: changed wording to make it more clear that by "object", I mean class-object.

Matt Anderson
Much clearer. And that makes sense. Is there any reason to use `__init__` though?
Jason Baker
`__new__` can do everything that `__init__` can do, but not the other way around. `__init__` can be more convenient to use though, in the same way that `__new__` and `__init__` relate in regular class instantiation. You have to remember to return something from `__new__` for example, but with `__init__` you don't.
Matt Anderson
+1  A: 

You can see the full writeup in the official docs, but basically, __new__ is called before the new object is created (for the purpose of creating it) and __init__ is called after the new object is created (for the purpose of initializing it).

Using __new__ allows tricks like object caching (always returning the same object for the same arguments rather than creating new ones) or producing objects of a different class than requested (sometimes used to return more-specific subclasses of the requested class). Generally, unless you're doing something pretty odd, __new__ is of limited utility. If you don't need to invoke such trickery, stick with __init__.

Ben Blank
I understand the difference between `__new__` and `__init__` for a regular class. I was asking why I would want to use them for a metaclass.
Jason Baker
Ah. Never mind, then. ^.^
Ben Blank