Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically adding methods with metaclass "__init__" vs "__new__"

Continuing the discussion from this question: Dynamically adding methods with or without metaclass, when doing the dynamic injetion, what is the difference and benefits/issues of doing it in the __new__ method vs. the __init__ method?

In the referenced question the new method is added by using setattr. If you do this in the__new__ method, you need to modify the dict parameter. Using the same example, it would be something like this:

class Meta(type)
    def __new__(cls, clsname, bases, dct):
        def my_method(self, x):
            return x in self.letters

        dct[my_method.__name__] = my_method
        return super(Meta, cls).__new__(cls, clsname, bases, dct)
like image 288
Arcanefoam Avatar asked Sep 18 '15 09:09

Arcanefoam


1 Answers

If you do this in the new method, you need to modify the dict parameter

Well, not necessarily, you can as well use setattr after you created the new class object, ie:

class Meta(type)
    def __new__(cls, clsname, bases, dct):
        def my_method(self, x):
            return x in self.letters

        newclass =  super(Meta, cls).__new__(cls, clsname, bases, dct)
        setattr(newclass, my_method.__name__, my_method)
        return newclass

So basically, in Meta.__init__ you can only modify the already instanciated class object, while in Meta.__new__ you can inspect and modify the parents and namespace before creating the class and modify the created class afterward.

So what's the point of using __init__ at all ? Well sometimes you don't need all the power __new__ gives you only want to modify the newly created class, and then __init__ saves you the extra boilerplate of creating the class.

like image 190
bruno desthuilliers Avatar answered Nov 15 '22 00:11

bruno desthuilliers