Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my metaclass implementation fail with a TypeError about not being able to create NoneType instances

I have the following Python code:

class MetaData(object):
    _md = {}

class _ClassMeta(type):
    def __new__(cls, clsname, bases, dct):
        ncls = super(_ClassMeta, cls).__new__(cls, clsname, bases, dct)
        MetaData._md[clsname] = ncls

class Meta(object):
    __metaclass__ = _ClassMeta

class Test(Meta):
    pass

When I try to execute it, I get this:

TypeError: Error when calling the metaclass bases
    cannot create 'NoneType' instances

on the line with class Test(Meta): I don't understand why. The metaclass's __new__ function evidently was called fine for the Meta class, but not for the derived Test class.

For those who ask "why" - I'm exploring runtime class registration and modification a la the ORM frameworks like Django and SqlAlchemy. This may not be how I'll finally produce my code, but I still would like an answer to why I'm getting the TypeError exception.

like image 403
paulluap Avatar asked Jan 10 '23 13:01

paulluap


1 Answers

Your problem is pretty simple: The __new__ method has to create an instance and return it. You're not returning anything, so it returns None.

Since this is a metaclass's __new__, that means that it's getting called to construct the Meta class object. So you've just defined Meta as being None, rather than as a class of type _ClassMeta. Which is a perfectly valid thing to do, hence no error there, but as soon as you try to do anything with it, like Meta(), you'll get an exception about NoneType not being callable or similar.

And that includes subclassing it. You can't subclass None, because it's not a type.

like image 155
abarnert Avatar answered Jan 17 '23 12:01

abarnert