THD
THD

Reputation: 13

Python metaclass use with object instantiation

With following code, I expect the output to be:

# meta.__new__
# meta.__new__
# meta.__init__
# Before instantiation of Entity
# meta.__call__
# __new__
# __init__
# __call__
#

Instead I got following output:

# meta.__new__
# meta.__new__
# meta.__init__
# Before instantiation of Entity
# meta.__call__
# __new__
# __init__
# Traceback (most recent call last):
#    File "test.py", line 39, in <module>
#       e(3,4)
# TypeError: 'NoneType' object is not callable

class MyMetaClass(type):
    def __new__(cls, name, bases, dct):
        print 'meta.__new__'
        return super(MyMetaClass, cls).__new__(cls, name, bases, dct)

    def __init__(cls, name, bases, dct):
        print 'meta.__init__'
        super(MyMetaClass, cls).__init__(name, bases, dct)

    def __call__(self, *more):
        print 'meta.__call__'
        super(MyMetaClass, self).__call__(*more)

class Entity(object):
    __metaclass__ = MyMetaClass

    def __new__(cls, *args, **kwargs):
        print '__new__'
        return super(Entity, cls).__new__(cls, *args, **kwargs)

    def __init__(self, x, y):
        print '__init__'
        self.x, self.y = x, y

    def __call__(self, x, y):
        print '__call__'
        self.x, self.y = x, y

if __name__ == '__main__':
    print 'Before instantiation of Entity'
    e = Entity(1,2)
    e(3,4)

Upvotes: 1

Views: 108

Answers (1)

jonrsharpe
jonrsharpe

Reputation: 121964

Note that MyMetaClass.__call__, which is being invoked on creation and instantiation of e, doesn't actually return anything, hence e is None afterwards. The minimal fix is therefore to:

class MyMetaClass(type):

    ...

    def __call__(self, *more):
        print 'meta.__call__'
        return super(MyMetaClass, self).__call__(*more)
      # ^ add return

But without an explanation of why you've implemented __new__ and __init__ and __call__ on the metaclass, including a less abstract example, it's hard to provide advice on what the most appropriate fix might be.

Upvotes: 1

Related Questions