summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaymond Hettinger <rhettinger@users.noreply.github.com>2020-05-11 17:00:53 -0700
committerGitHub <noreply@github.com>2020-05-11 17:00:53 -0700
commit21cdb711e3b1975398c54141e519ead02670610e (patch)
treebbe4a1006ff4a8d3f6e280eb556b7c25cccb1f4c
parent4804b5b3df82e7892ca0550b02f902bcfc16bb48 (diff)
downloadcpython-git-21cdb711e3b1975398c54141e519ead02670610e.tar.gz
bpo-40571: Make lru_cache(maxsize=None) more discoverable (GH-20019)
-rw-r--r--Doc/library/functools.rst26
-rw-r--r--Lib/functools.py11
-rw-r--r--Lib/test/test_functools.py19
-rw-r--r--Misc/NEWS.d/next/Library/2020-05-09-15-38-25.bpo-40571.kOXZGC.rst2
4 files changed, 57 insertions, 1 deletions
diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst
index 856c1c790a..204e66ae5a 100644
--- a/Doc/library/functools.rst
+++ b/Doc/library/functools.rst
@@ -26,6 +26,32 @@ function for the purposes of this module.
The :mod:`functools` module defines the following functions:
+.. decorator:: cache(user_function)
+
+ Simple lightweight unbounded function cache. Sometimes called
+ `"memoize" <https://en.wikipedia.org/wiki/Memoization>`_.
+
+ Returns the same as ``lru_cache(maxsize=None)``, creating a thin
+ wrapper around a dictionary lookup for the function arguments. Because it
+ never needs to evict old values, this is smaller and faster than
+ :func:`lru_cache()` with a size limit.
+
+ For example::
+
+ @cache
+ def factorial(n):
+ return n * factorial(n-1) if n else 1
+
+ >>> factorial(10) # no previously cached result, makes 11 recursive calls
+ 3628800
+ >>> factorial(5) # just looks up cached value result
+ 120
+ >>> factorial(12) # makes two new recursive calls, the other 10 are cached
+ 479001600
+
+ .. versionadded:: 3.9
+
+
.. decorator:: cached_property(func)
Transform a method of a class into a property whose value is computed once
diff --git a/Lib/functools.py b/Lib/functools.py
index f05b106b62..87c7d87438 100644
--- a/Lib/functools.py
+++ b/Lib/functools.py
@@ -10,7 +10,7 @@
# See C source code for _functools credits/copyright
__all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES',
- 'total_ordering', 'cmp_to_key', 'lru_cache', 'reduce',
+ 'total_ordering', 'cache', 'cmp_to_key', 'lru_cache', 'reduce',
'TopologicalSorter', 'CycleError',
'partial', 'partialmethod', 'singledispatch', 'singledispatchmethod',
'cached_property']
@@ -889,6 +889,15 @@ except ImportError:
################################################################################
+### cache -- simplified access to the infinity cache
+################################################################################
+
+def cache(user_function, /):
+ 'Simple lightweight unbounded cache. Sometimes called "memoize".'
+ return lru_cache(maxsize=None)(user_function)
+
+
+################################################################################
### singledispatch() - single-dispatch generic function decorator
################################################################################
diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py
index b3893a1556..e122fe0b33 100644
--- a/Lib/test/test_functools.py
+++ b/Lib/test/test_functools.py
@@ -1432,6 +1432,25 @@ class TestTopologicalSort(unittest.TestCase):
self.assertEqual(run1, run2)
+class TestCache:
+ # This tests that the pass-through is working as designed.
+ # The underlying functionality is tested in TestLRU.
+
+ def test_cache(self):
+ @self.module.cache
+ def fib(n):
+ if n < 2:
+ return n
+ return fib(n-1) + fib(n-2)
+ self.assertEqual([fib(n) for n in range(16)],
+ [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610])
+ self.assertEqual(fib.cache_info(),
+ self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16))
+ fib.cache_clear()
+ self.assertEqual(fib.cache_info(),
+ self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0))
+
+
class TestLRU:
def test_lru(self):
diff --git a/Misc/NEWS.d/next/Library/2020-05-09-15-38-25.bpo-40571.kOXZGC.rst b/Misc/NEWS.d/next/Library/2020-05-09-15-38-25.bpo-40571.kOXZGC.rst
new file mode 100644
index 0000000000..476770f697
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-05-09-15-38-25.bpo-40571.kOXZGC.rst
@@ -0,0 +1,2 @@
+Added functools.cache() as a simpler, more discoverable way to access the
+unbounded cache variant of lru_cache(maxsize=None).