Removing non-input parameters when using functools LRU cache?

Viewed 51

I have a function that uses functools LRU cache, but I want to pass in some non-input parameters e.g. "a"

import functools
import random

def foo(d, a):
    @functools.lru_cache()
    def bar(d):
        random.seed(d)
        nonlocal a
        a = []
        s = 0
        for i in range(100):
            r = random.random()
            a.append(r)
            s += r
        if s < 50:
            return True
        else:
            return False
    return bar(d)

But when I use these functions, "a" is not changed:

a = []
print(foo(random.randint(0, 100), a))
print(a)

What's going on? Also is this the right way to use functools, nested?

Update

I used this in the end i.e. with global and without foo:

@functools.lru_cache()
def bar(d):
    global a
    random.seed(d)
    ...
1 Answers

It does not change a because you are redefining it in the function. You are basically doing this:

def foo(a):
    a = [1, 2, 3]
    return a

a = []
foo(a)

So the outer a will remain as empty list after the function call. You may say but I'm using nonlocal keyword so I should be referencing to the original a. In fact, you are referencing to the parameter. So the effect is same as above code. If you run below code with and without nonlocal you can see what's going on:

def foo(a):
    def bar():
        # nonlocal a
        a = [1, 2, 3]
        print("bar", a)
    bar()
    print("foo", a)

a = []
foo(a)
print("global", a)

Outputs:

bar [1, 2, 3]
foo []
global []

And when you use nonlocal a:

bar [1, 2, 3]
foo [1, 2, 3]
global []

What you can do in your function is delete nonlocal a statement since it does not have any effect on the outer a and replace a = [] with a.clear().

Related