0

I try to understand memorization, particularly regarding nonlocal mem with the code below:

def mem_last(f):
    mem = 0
    def helper(x):
        print("mem = ", mem)
        mem = f(x + mem)
        return mem
    return helper

def mem_last1(f):
    mem = {"0": 0}
    def helper(x):
        print("mem = ", mem)
        mem["0"] = f(x + mem["0"])
        return mem["0"]
    return helper
    
def f(x):
    print("x = ", x)
    return x

f = mem_last(f) 
#f = mem_last1(f)

print(f(0))

When I use f = mem_last(f), where mem is a scalar, there is an error:

py mem.py

Traceback (most recent call last):
  File "mem.py", line 15, in <module>
    print(f(0))
  File "mem.py", line 4, in helper
    print("mem = ", mem)
UnboundLocalError: local variable 'mem' referenced before assignment

If I use f = mem_last1(f), where mem is a dict, there is no error and it works well.

Please explain why there is a difference between a dict and a scalar var. Thank you very much.

PS: I am using 3.7.7 64 bit on Windows 10. I have read the thread you provide and I fix it by add a line "nonlocal mem" before 'print("mem = ", mem)'.

However, my question is why I do not need to add line "nonlocal mem" when mem is a dict or a list, and no error occur. So why python treats scalar different from dict or list?

Areza
  • 5,623
  • 7
  • 48
  • 79
  • Your issue is `mem = f(x + mem)` line which redefines `mem` as a local variable. Python is a dynamic language. – Selcuk Jul 09 '20 at 07:25
  • There are several questions on SO with some great answers explaining this behaviour and proposing some workarounds. The most complete is [this](https://stackoverflow.com/q/2009402/6682517) IMHO (both the question and the accepted answer). – Sergey Shubin Jul 09 '20 at 07:31
  • Thank you very much. The error is at line: print("mem = ", mem). I fix it by add a line "nonlocal mem" before this line. However, my question is why I do not need to add line "nonlocal mem" when mem is a dict or a list. – Long Tran Dai Jul 09 '20 at 09:04
  • because you're not _reassigning_ the name the dict/list points to, you're simply mutating it in place. – acushner Jul 09 '20 at 11:18

0 Answers0