When fib() is called without the second parameter, the Python interpreter will instantiate an empty dictionary referenced by fib_vals. That dictionary is, effectively, persistent between similar invocations of fib().
In order to understand what's going on, it might help you to change your code (purely for demonstration purposes) thus:
FV = {}
def fib(n, fib_vals={}):
global FV
FV = fib_vals
if fib_vals.get(n):
return fib_vals[n]
if n <= 1:
return n
fib_vals[n] = fib(n - 1) + fib(n - 2)
return fib_vals[n]
if __name__ == '__main__':
print(fib(10))
print(FV)
print(fib(9))
print(FV)
You will notice that the value of FV doesn't change. It will change if/when fib() is invoked with a higher value for the first parameter.
EDIT: Correction: fib_vals is instantiated when fib() is parsed by the Python interpreter and not when fib() is first called.