How to correctly change the internal state of a closure in python?

I am looking into closures, but I am a bit confused on how to change their internal state.

Consider the following two examples:

def mean():
    sample = []

    def inner_mean(number):
        sample.append(number)
        return sum(sample) / len(sample)

    return inner_mean

and

def lpf(fs):
    y = 0.0

    def _lpf(fc, u):
        y = (1 - fc / fs) * y + fc / fs * u
        return y

    return _lpf

The first case runs without any problem, whereas the second gives me that variable ‘y’ in enclosing scope is referenced before assignment.

Why this won’t happen in the first example? And how shall I modify the second example to make it work?

To be more clear, once I created a function I want the value of the internal state y to be remembered at each function call.

For example, if do the following:

lpf_zero_three = lpf(0.3)

lpf_zero_three(1.2, 0.2)  
lpf_zero_three(1.2, 3.1) 

the returned value of lpf_zero_three(1.2, 3.1) call shall depend on the value y obtained from call of lpf_zero_three(1.2, 0.2).

>Solution :

The error occurs because there is an assignment to y in the inner function (i.e. there is y =). This causes a new local variable named y to be created, which hides the outer variable y.

There is y also on the right-hand side of y=. That references the same local y, which is not initialized yet.

Since your intention is to use the outer variable y instead of creating a new inner variable, you should put this at the beginning of function _lpf:

nonlocal y

In the other example, there’s no problem because there is no assignment to sample.

Leave a Reply