From my understanding the __call__
method inside a class implements the function call operator, for example:
class Foo:
def __init__(self):
print("I'm inside the __init__ method")
def __call__(self):
print("I'm inside the __call__ method")
x = Foo() #outputs "I'm inside the __init__ method"
x() #outputs "I'm inside the __call__ method"
However, I'm going through the Python Cookbook and the writer defined a metaclass to control instance creation so that you can't instantiate an object directly. This is how he did it:
class NoInstance(type):
def __call__(self, *args, **kwargs):
raise TypeError("Can't instantaite class directly")
class Spam(metaclass=NoInstance):
@staticmethod
def grok(x):
print("Spam.grok")
Spam.grok(42) #outputs "Spam.grok"
s = Spam() #outputs TypeError: Can't instantaite class directly
However, what I don't get is how s()
wasn't called, yet it's __call__
method was called. How does this work?
Metaclasses implement how the class will behave (not the instance). So when you look at the instance creation:
x = Foo()
This literally "calls" the class Foo
. That's why __call__
of the metaclass is invoked before the __new__
and __init__
methods of your class initialize the instance.
As @Take_Care_ pointed out in the comments one great ressource on metaclasses is ionelmc's blog post about "Understanding Python metaclasses". One image in that blog post directly applies to your situation:
The image is directly copied from the blog post.
A class is simply an instance of its metaclass. Since the metaclass defines __call__()
, calling the instance of the metaclass, i.e. the class, as a function, i.e. as a constructor, will invoke it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With