Today, while tackling this question on Project Euler, I stumbled upon an intriguing use-case for employing mutable objects as default arguments in Python functions. Typically, this practice is discouraged due to the risk of unintended side effects, a concept extensively discussed in the book "Fluent Python." However, I believe I have a scenario where this approach might be justified.
I am currently working on calculating a mathematical sequence that could greatly benefit from caching. The sequence adheres to a well-defined and regular rule, making it suitable to share the same cache across all calculations. Below is the code snippet in question:
LIMIT = int(1e6)
def collatz(n, cache={}): # Cache acts as a static variable here.
if n == 1:
return 1
if n not in cache:
cache[n] = 1 + (collatz(3 * n + 1) if n % 2 else collatz(n // 2))
return cache[n]
max_pair = max(((collatz(x), x) for x in range(LIMIT // 2, LIMIT)))
print(max_pair[1])
I am curious to hear your thoughts on whether this use of a mutable default argument is a clever application of the language's characteristics or if it should be avoided due to potential drawbacks. Have you encountered similar scenarios, and how did you handle caching in such situations?
Your insights and feedback are greatly appreciated.
Thanks in advance!