A name assigned inside a function is local to it. Python decides this when it reads the function: if the function assigns total anywhere, every total in it's local, so total = total + amount raises UnboundLocalError. The fix is to pass values in and return results, rather than reaching for global.
A function defined inside another one can read the outer function's variables, and keeps them after the outer function returns. That's a closure, and it lets you make configured functions: make_discounter(0.1) returns a function that always applies 10%. To change an outer variable from the inner function, declare it nonlocal.
One trap: functions created in a loop look up loop variables when they run, not when they're made, so they all see the last value. Freeze the value with a default argument: lambda x, r=r: x * r.