DEV Community

Cover image for ๐Ÿ•ต๐Ÿฝ Investigating python Callables : functions, methods and more...
Wassaf Shahzasd
Wassaf Shahzasd

Posted on

๐Ÿ•ต๐Ÿฝ Investigating python Callables : functions, methods and more...

The way python handles functions is a bit unique and the star โญ of the show is the "self" argument passed to every function defined within a class, But have you ever wondered, how self is passed to the function? We never pass it during the call.
How does it get there ? and how can we replicate it ?

wondering

Well in this article, we will try to understand and replicate it. Lets put the fun in functions๐ŸŽ‰.

๐Ÿงฉ Types of functions in Python.

First, we need to understand is the type of functions. When using mypy, we annotate them as a Callable but that is not a python standard type. To figure this out lets get coding.
(I know that world is spelt wrong, GET OFF MY BACK)

function type

Running the above code gives us the following results.

<class 'function'>
Enter fullscreen mode Exit fullscreen mode

A bit anticlimactic, so a function is of type function, what about methods (foreshadowing...) or functions within a classes ?

functions in class

Running the following code gives us a bit more idea. The Output shows us

<bound method Foo.foo of <__main__.Foo object at 0x0000020B6B999D00>>
<class 'method'>
<function Foo.foo at 0x0000020B6B9B91C0>
Enter fullscreen mode Exit fullscreen mode

We learn 3 things from this.

  • The type of a function belonging to a class is method
  • The reference of a method is a bound method tied down to the instance.
  • Interestingly, a method on a class level is treated as a function.

๐Ÿคจ How does self get there ?

When an instance of a class is created, the functions defined within them get replaced by descriptors, with the instance passed to them as the first argument.
You can learn more about descriptors from here. The TLDR is, that they are getter and setters for instance attributes.
Try the following code and see what happens ๐Ÿคฉ

Descriptor code

Checking the type of the function, reveals a funny thing. The type of the bar function has been changed to a method and is bound to the int object 10.

bound method to int

๐Ÿค” What if you don't want a bound method ?

In the above example, We create a bound method to tie some arguments to the function. What if you don't want to do that ? What if you don't want to use the get method ? How can we recreate the above functionality, Well we use decorators !!!!!.

pseudo bound method using decorators

If you don't want to use the decorator synthetic sugar, you can use this.

Higher order functions

๐Ÿ˜Ž One more thing.

Like we saw above methods are defined as a function type at the class level. Which means the first argument is unbound and we can do this.

Using method as a function

๐ŸŽ† Conclusion

Thanks for following this article and hope you learned something new about functions in python. Word of caution, don't use this in production level code, unless you want to annoy your co-workers, if so, go crazy.
Just cause we could to these shenanigans, doesn't mean we should.

Jeff-goldblum-meme

Top comments (0)