I am new to Python coming from C++ background and this is the first time I am seeing a language which contains nothing but objects. I have just learned that class and functions are also just objects. So, is there a way to convert the following function to a class?
In [1]: def somefnc(a, b):
...: return a+b
...:
I have first tried assigning the __call__ variable to None to take away the "callable nature" from the function. But as you can see, the __call__ was successfully replaced by None but this didn't cause the function to stop adding numbers when called, though, somefnc.__call__(1,3) was working before assigning somefnc.__call__ to None
In [2]: somefnc.__dict__
Out[2]: {}
In [3]: somefnc.__call__
Out[3]: <method-wrapper '__call__' of function object at 0x7f282e8ff7b8>
In [4]: somefnc.__call__ = None
In [5]: x = somefnc(1, 2)
In [6]: print(x)
3
In [7]: somefnc.__call__
In [8]: print(somefnc.__call__(1, 2))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
ipython-input-8-407663da97ca
in <module>()
----> 1 print(somefnc.__call__(1, 2))
TypeError: 'NoneType' object is not callable
In [9]: print (somefnc(1,2))
3
In [10]:
I am not doing this for developing purpose here, so claiming this to be a bad practice will not make any sense. I am just trying to understand Python very well. Of course, for development purpose, I could rather create a class than to convert a function to one!
After robbing the function off its ability to add two numbers, I am thinking of assigning a valid function to the attribute somefnc.__init__ and some members by modifying somefun.__dict__, to convert it to a class.
In Python functions are instances of the
functionclass. So I'll give you a general answer about any class and instance.In Python all special methods (the ones with double underscores in the prefix and the postfix) are accessed from the class when triggered via operators, not from the instance.
All methods are accessed via the instance first, when accessed by name. The difference is due to different search mechanics. When you access a method/attribute by name, you invoke
__getattribute__which will first search in the instance's namespace by default. When you trigger a method via operators,__getattribute__is not invoked. You can see it in the disassembly.As you can see, there is no
LOAD_ATTRin the first case. The[]operator is assembled as a special virtual-machine instructionBINARY_SUBSCR.