Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Making Objects Callable

00:00 Normally, when you create an object from a class you interact with it by calling its methods like some object dot some method. But what if you could use your object just like a function?

00:13 That’s where being callable comes into play. What is a callable object again? A callable is any object that you can call using a pair of parentheses and optionally a series of arguments.

00:26 You’ve been using them all the time. For example, functions, classes, and methods. To make your own you can add the .__call__() special method to your class.

00:41 Any instance of a class with a .__call__() method behaves like a function.

00:48 To see how this works in practice, let’s create a Factorial class that caches already computed values for efficiency. This will help you understand how callables work in Python.

01:00 In this example, you’ll implement the call magic method because you want to make the Factorial class itself callable. This means that instead of using a method like factorial.calculate(), you’ll be able to directly call the class instance with a number like factorial(5) or factorial(4).

01:21 Let’s see how that goes. Okay, let’s start by defining the class. So class Factorial:. Then you need to set up the class with an .__init__() method that initializes a a cache dictionary.

01:36 This will store the results of factorials you’ve already calculated so you don’t have to calculate them again. def __init__(self): and let’s call it self.cache = {} because you want a dictionary.

01:55 Now comes the key part, the __call__ magic method. By defining this method, you are making the Factorial class callable. So this means that you use an instance of Factorial just like you’d use a function. self and n.

02:15 Now you have to check if the factorial of n that you’re calculating has already been calculated or not. If it is, you just return it right away without the need to actually recalculate it.

02:28 So if n in self.cache:

02:34 you simply return self.cache [n], and if the factorial isn’t cached, you calculate it. For zero and one the factorial is one, for any other number you calculate it by multiplying n by the factorial of n - 1 so you create a recursion.

02:57 After computing the result, you store it in the cache and then return it. So let’s do that. if n == 0 or n == 1, the result would be just 1.

03:13 Anything else result would be n * the factorial or self of (n - 1).

03:26 After that, you have to store this result in your cash dictionary. So self.cache[n] equals the result you just calculated, and finally, you just return this result

03:42 and that’s the entire logic that you needed. But to just make this better, let’s create a developer-friendly string representation by using the .__repr__() magic method that you explored earlier.

03:56 This would show what’s currently in the cache. def __repr__(self):

04:05 You’re returning first the class name, so Factorial,

04:10 and then you’re saying this is the cache. So cache = {self.cache}.

04:20 And that’s about it. Now let’s create an instance of the Factorial class. So factorial = Factorial() factorial class with the parentheses, so you’re calling it, and then let’s print, for example, the factorial of five.

04:40 So factorial(5), let’s see what we get.

04:46 And you get 120. So this works. There you go. The __call__ method has made the factorial class itself callable. Instead of writing something like factorial.calculate() or factorial.compute(5), you can simply write factorial(5).

05:05 Good job.

Become a Member to join the conversation.