Building Stateful Functions
00:00 Our next example looks at functions that can retain their state between function calls. Often in Python, we use the object-oriented programming principle, where you have an object which has a state, and you can change that state, for example, changing the value of a data attribute throughout the lifetime of the object.
00:18 But sometimes you may not want the overhead of creating a class, or perhaps you’re using a programming paradigm such as functional programming where you do not use classes.
00:29 In these cases, you can have a function that retains the state, the closures you worked with in section one were examples of this. But let’s look at a different example.
00:40
You can open a new script called stateful_functions.py
.
00:45
You can create a function called cumulative_average()
.
00:50
This will be the outer function. So you can define an inner function. You can just simply call it average()
. And this will accept a value as you’ve seen already.
00:59 The inner function is the function you’ll be using in your global scope, and therefore you’ll be calling this function and passing a value to it. And what you’d like this function to do is to recalculate the average each time you add a value.
01:14
Since you want each call of this inner function to have information from all the previous calls, you can create a list called data
in the enclosing scope.
01:24
So this is a local variable within the outer function cumulative_average()
. The inner function average()
can then add the new value to the list data
.
01:36
Since data
is a list, it’s mutable. You do not need to use the nonlocal
keyword because you’re mutating an existing list. And the function average()
can then return the sum of the data
divided by the length of the data
.
01:52
And this gives you the average. So what you’re doing is you are always adding the latest value to the list data
, and finding the average of all the values you have in the list.
02:04
Since the inner function average()
is the one you want to use in the global scope, the outer function must return average
. You can test this out by creating, let’s call it stream_average
, and this will be the function returned by cumulative_average
.
02:23 Let’s start by calling this function the first time
02:28
and you can pass a value to it, let’s say 12
. And let’s print out its output. You can run the script, which in my case I call stateful_functions
.
02:40
And so far the average is 12
since there’s only one value.
02:47
Let’s call a function a second time with the value 13
.
02:52
And now the second time you call this function, the average is 12.5
because the average of 12
and 13
is 12.5
.
03:06
And as you can see, each time you call stream_
average
, the average is changing. In our final call, the average of the numbers 12, 13, 14, 15 is 13.5.
03:19
Therefore, even though the calls to stream_average
are four separate calls, each one of those function calls is communicating with the previous ones.
03:29
Since all of those functions use the same list data
with all the values, this is what we mean by a function that maintains its state.
03:39 So let’s review what stateful functions are before we move on to another example. Since a closure is a function that has access to data defined in its enclosing scope, calls of the closure function share the same data.
03:53
In this example, calls to the inner function average()
, all share the same pool of values stored in data
. Every time you call average()
, you add the new value to the central repository, the list data
.
Become a Member to join the conversation.