Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with making object callable in python

Tags:

I wrote code like this

>>> class a(object):         def __init__(self):             self.__call__ = lambda x:x  >>> b = a() 

I expected that object of class a should be callable object but eventually it is not.

>>> b()  Traceback (most recent call last):     File "<pyshell#5>", line 1, in <module>         b() TypeError: 'a' object is not callable >>> callable(b) False  >>> hasattr(b,'__call__') True >>>  

I can't understand why. Please help me.

like image 652
kjshim Avatar asked Nov 10 '09 06:11

kjshim


People also ask

Why is my object not callable Python?

The “int object is not callable” error occurs when you declare a variable and name it with a built-in function name such as int() , sum() , max() , and others. The error also occurs when you don't specify an arithmetic operator while performing a mathematical operation.

Why is my class not callable Python?

Python attempts to invoke a module as an instance of a class or as a function. This TypeError: 'module' object is not callable error occurs when class and module have the same name. The import statement imports the module name not the class name.

Are Python objects callable?

Python's functions are callable objects So, every function in Python is a callable, meaning it's an object that you're able to call.

How do you make a class object callable in Python?

Simply, you make an object callable by overriding the special method __call__() . __call__(self, arg1, .., argn, *args, **kwargs) : This method is like any other normal method in Python. It also can accept positional and arbitrary arguments.


2 Answers

Special methods are looked up on the type (e.g., class) of the object being operated on, not on the specific instance. Think about it: otherwise, if a class defines __call__ for example, when the class is called that __call__ should get called... what a disaster! But fortunately the special method is instead looked up on the class's type, AKA metaclass, and all is well ("legacy classes" had very irregular behavior in this, which is why we're all better off with the new-style ones -- which are the only ones left in Python 3).

So if you need "per-instance overriding" of special methods, you have to ensure the instance has its own unique class. That's very easy:

class a(object):     def __init__(self):         self.__class__ = type(self.__class__.__name__, (self.__class__,), {})         self.__class__.__call__ = lambda x:x 

and you're there. Of course that would be silly in this case, as every instance ends up with just the same "so-called per-instance" (!) __call__, but it would be useful if you really needed overriding on a per-individual-instance basis.

like image 126
Alex Martelli Avatar answered Oct 18 '22 10:10

Alex Martelli


__call__ needs to be defined on the class, not the instance

class a(object):     def __init__(self):         pass     __call__ = lambda x:x 

but most people probably find it more readable to define the method the usual way

class a(object):     def __init__(self):         pass     def __call__(self):         return self 

If you need to have different behaviour for each instance you could do it like this

class a(object):     def __init__(self):         self.myfunc = lambda x:x      def __call__(self):         return self.myfunc(self) 
like image 28
John La Rooy Avatar answered Oct 18 '22 12:10

John La Rooy