I'm wondering about the more intricate differences between functions and callable objects. For example, if you do:
return 2 + 4
return 2 + 4
sys.getsizeof(foo1) # returns 136
sys.getsizeof(foo2) # returns 1016
Functions are also callable objects:
>>> foo1.__call__ <method-wrapper '__call__' of function object at 0x105bafd90> >>> callable(foo1) True
But a class needs to keep track of more information; it doesn't matter here that you gave it a
__call__ method. Any class is bigger than a function:
>>> import sys >>> def foo1(): ... return 2 + 4 ... >>> class foo3: ... pass ... >>> sys.getsizeof(foo1) 136 >>> sys.getsizeof(foo3) 1056
A function object is a distinct object type:
>>> type(foo1) <class 'function'>
and is reasonably compact because the meat is not actually in the function object but in other objects referenced by the function object:
>>> sys.getsizeof(foo1.__code__) 144 >>> sys.getsizeof(foo1.__dict__) 240
And that's it really; different types of objects have different sizes because they track different things or use composition to store stuff in other objects.
You can use the
type(foo1) return value (or
types.FunctionType, which is the same object) to produce new function objects if you so desire:
>>> import types >>> types.FunctionType(foo1.__code__, globals(), 'somename') <function foo1 at 0x105fbc510>
which is basically what the interpreter does whenever a
def function(..): ... statement is being executed.
__call__ to make custom classes callable when that makes sense to your API. The
enum.Enum() class is callable, for example, specifically because using the call syntax gives you a syntax distinct from subscription, which was used for other purposes.