Issue 10930: dict.setdefault: Bug: default argument is ALWAYS evaluated, i.e. no short-circuit eval (original) (raw)

Hello!

Is it intentional, that the default argument is ALWAYS evaluated, even if it is not needed???

Is it not a bug, that this method has no short-circuit eval (http://en.wikipedia.org/wiki/Short-circuit_evaluation) ??

Example1:

infinite = 1e100

one_div_by = {0.0 : infinite}

def func(n): return one_div_by.setdefault(float(n), 1/float(n))

for i in [1, 2, 3, 4]: print i, func(i) print one_div_by

works!!

for i in [0, 1, 2, 3, 4]: # added 0 -> FAIL! print i, func(i) print one_div_by

fail!!

Example2:

fib_d = {0 : 0, 1 : 1}

def fibonacci(n): return fib_d.setdefault(n, fibonacci(n-1) + fibonacci(n-2))

for i in range(10): print i, fibonacci(i) print fib_d

setdefault() is a method, its arguments are evaluated then the function is called. This is not a bug, and this behavior cannot change.

If you are trying to "cache" the computation of a function, you should try "memoizing" techniques, like the one mentioned here: http://code.activestate.com/recipes/52201-memoizing-cacheing-function-return-values/ Then you can write::

@Memoize
def fib(n):
    return fib(n-1) + fib(n-2)
fib.memo = {(0,): 1, (1,): 1}

@Memoize
def func(n):
    return 1/float(n)
func.memo = {(0.0,): infinite}