Python has some methods that are special in a way . If these methods are created inside a class, they can bring in some unique behaviors . We will talk about the method '__call__' today.
When we create a class (old/new style), and an instance of that class, that instance has certain ...features by default.
When we create a class (old/new style), and an instance of that class, that instance has certain ...features by default.
class MyClass: pass m = MyClass() print dir(m)
Consider above class . Things to note:
- I am using Python 2..7 . So above class is an old-style class (since I did not inherit 'object' into it).
- The class has no methods defined in it.
Now lets run this program. Here's the output:
['__doc__', '__module__']
Let's try calling the instance 'm' with parenthesis.
>>> m <__main__.MyClass instance at 0x000000000332E488> >>> m() Traceback (most recent call last): File "<pyshell#9>", line 1, in <module> m() AttributeError: MyClass instance has no __call__ method
What happened here. It threw an Attribute Error saying I don't have a __call__ method.
BUT I NEVER called the method __call__ anywhere in my program. Then why is it giving me this error statement.
Turns out. That's what is looked up inside a class when someone tries to call an instance with arguments using parenthesis.
Another question. What's about new style classes. Do they also need them explicitly. Let's change our class a bit.
class MyClass(object): pass m = MyClass()
Things to note: Now we have inherited object into our class making it a new-style class.
>>> m() Traceback (most recent call last): File "<pyshell#10>", line 1, in <module> m() TypeError: 'MyClass' object is not callable
Seems like, we DO NEED to declare the __call__ method. But the Error type has changed now and the message too.
Lets now try to add this method and see what happens.
class MyClass(object): def __call__(self, *args): return sum(args) m = MyClass() print m(1,2,3,4,5) >>>15
Now if the above analogy hold true all throughout Python, that means functions must be having this method by default. Let's find if it's true.
>>> def myFun(num, power): return num**power >>> myFun(2, 4) 16 >>> dir(myFun) ['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name'] >>> myFun.__call__(2,4) 16
As suspected, every function ALWAYS will have a __call__ method supported since all functions are callable.
No comments:
Post a Comment