Loading video player…

Using .__call__() to Create Callable Instances

00:00 Before jumping back into examples, let’s quickly review what .__call__() does in your classes. It turns class instances into callable objects, meaning you can use them like functions, and works just like a regular instance method.

00:13 So it’s important to remember that it also receives self as its first argument followed by accepting any extra arguments you define. Open up your code editor of choice to explore some examples.

00:26 Name the first file counter.py. And for starters, you’ll create a Counter class where each instance keeps a count. The only functionality it’ll have is the ability to increment that count in two ways.

00:39 class Counter: def __init__() with the parameter self. Set the instance attribute self.count to zero.

00:49 Next, define the increment() method. It also has the parameter self, and increases the value of .self.count by one when called. self.count += 1.

01:01 And now __call__(): def __call__() self

01:07 call self.increment(). Don’t forget it has a self parameter, just like any other instance method. But despite being a special method, the content of __call__() has no special requirements or limitations.

01:20 Save the file, and I’ll open the integrated terminal for this. Make it a bit larger, and open the REPL. Since this REPL was opened from the same directory as counter.py, you can import a class from it like so.

01:35 From counter import Counter and create a counter. counter equals the result of calling Counter(). To see that it works, you can call counter’s .increment() method.

01:46 counter.increment(), and check the count.

01:51 counter.count is 1. Seems to be working so far. Now try calling counter a couple times. counter(), counter().

02:02 Now check counter.count: 3. Hey, it works. So this small example illustrates how useful callable instances are for creating elegant interfaces.

02:14 For this purpose, you can treat the counter itself as the action count one more, instead of calling a method. Callable instances are great for straightforward classes like this where instances have a very clear and specific action.

02:28 For another example, create the file power.py.

02:40 Another use of callable instances is to create function factories. A class that produces instances that can be thought of as configurable functions. You’ll write a class called PowerFactory whose instances act as powers of functions, raising numbers to a given power. class PowerFactory: def __init__ (self, exponent=2):.

03:05 Set self.exponent to exponent.

03:09 The initializer here configures the instance by setting the .exponent attribute with a default value of 2. def __call__() with the parameter self and base, and all the .__call__() has to do is apply the built-in exponentiation operator with the base passed to it and the instance’s .exponent attribute.

03:29 So return base**self.exponent. If this is a little confusing, don’t worry. It’ll be clear when you see it in action. Save the file, clear the REPL. From power import PowerFactory, and create the first function from this factory: square_of.

03:52 square_of = the result of calling PowerFactory() passing in the integer 2. Because you pass 2, 2 will be the exponent applied whenever you call square_of().

04:02 So try calling it with the integer 3: square_of(3) returns 9, which is three times three. square_of(6) returns 36, 6 squared.

04:15 And since PowerFactory is a factory, you can keep using it to produce these power functions. Say, cube_of equals PowerFactory() passing in 3.

04:26 So when you call cube_of(3), you get cube_of (3): 27, 3 times 3 times 3.

04:33 And cube_of(6) returns 216, which well, my calculator tells me that this is 6 cubed. I’m sure your mind is already swimming with the potential uses of this pattern and you’re eager for more.

04:47 Well hold on. Next up, we take a slight detour to discuss a little more about special methods in Python. Specifically, how .__call__() differs from .__init__().

Become a Member to join the conversation.