0

I'm trying to understand metaclasses.

I already read this answer and I tried to use a custom __call__ like this :

#!/usr/bin/env python3                                                                                               

class MetaTest(type):
    def __call__(cls, *args, **kwargs):
        print("MetaTest.__call__ called.")
        return super().__call__(cls, *args, **kwargs)


class Test:
    __metaclass__ = MetaTest


if __name__ == '__main__':
    Test()

I expected Test.__class__.__call__ to be called at instanciation, and Test.__class__ to be an instance of MetaTest, but it's not the case since I don't have an output when running this script.

So why isn't MetaTest.__call__ called at Test instanciation?

Community
  • 1
  • 1
vmonteco
  • 14,136
  • 15
  • 55
  • 86
  • 1
    That's not the correct syntax for metaclass usage in Python 3.x: https://docs.python.org/3.0/whatsnew/3.0.html#changed-syntax. If you fix that, you will see the method get invoked as expected. – jonrsharpe Jan 13 '17 at 23:38
  • @jonrsharpe Indeed! I corrected it and `__class__.__call__` was called. Still have an error but that's an other question, this one is solved :) . – vmonteco Jan 13 '17 at 23:51

1 Answers1

1

You are using the Python 2 syntax for metaclasses - but your shebang line and tags indicate you are running it on Python 3.

Just change your class declaration to declare the metaclass using Python' 3 way:

#!/usr/bin/env python3                                                                                               

class MetaTest(type):
    def __call__(cls, *args, **kwargs):
        print("MetaTest.__call__ called.")
        return super().__call__(cls, *args, **kwargs)


class Test(metaclass=MetaTest):
    pass

if __name__ == '__main__':
    Test()

Declaring a __metaclass__attribute on the class body has no effect in Python 3- but since it is just an attribute declaration, it raises no error either.

jsbueno
  • 99,910
  • 10
  • 151
  • 209