New submission from Benoit B <h...@benbernardblog.com>:
I don't know if I'm missing something, but there's a behavior of functools.lru_cache() that I currently don't understand. As the documentation states: "If typed is set to true, function arguments of different types will be cached separately. For example, f(3) and f(3.0) will be treated as distinct calls with distinct results." For a function accepting only positional arguments, using typed=False doesn't seem to be working in all cases. >>> import functools >>> >>> @functools.lru_cache() # Implicitly uses typed=False >>> def func(a): ... return a >>> >>> func(1) >>> func(1.0) >>> >>> print(func.cache_info()) CacheInfo(hits=0, misses=2, maxsize=128, currsize=2) Instead, I would have expected: CacheInfo(hits=1, misses=1, maxsize=128, currsize=2) So it looks like 1 and 1.0 were stored as different values even though typed=False was used. After analyzing the source code of _functoolsmodule.c::lru_cache_make_key(), I found what follows: if (!typed && !kwds_size) { if (PyTuple_GET_SIZE(args) == 1) { key = PyTuple_GET_ITEM(args, 0); if (PyUnicode_CheckExact(key) || PyLong_CheckExact(key)) { <<< it appears that a 'float' would cause 'args' (a tuple) to be returned as the key, whereas an 'int' would cause 'key' /* For common scalar keys, save space by (an int) to be returned as the key. So 1 and 1.0 generate different hashes and are stored as different items. dropping the enclosing args tuple */ Py_INCREF(key); return key; } } Py_INCREF(args); return args; } At some point in the past, the above code section looked like this: if (!typed && !kwds) { Py_INCREF(args); return args; } So no matter what the type of the argument was, it was working. Am I somehow mistaken in my analysis or is this a bug? ---------- components: Library (Lib) messages: 361404 nosy: bbernard priority: normal severity: normal status: open title: @functools.lru_cache() not respecting typed=False type: behavior versions: Python 3.8 _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue39554> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com