Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
b821868e
Commit
b821868e
authored
May 26, 2019
by
Raymond Hettinger
Committed by
GitHub
May 26, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bpo-36772 Allow lru_cache to be used as decorator without making a function call (GH-13048)
parent
aaf47caf
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
53 additions
and
12 deletions
+53
-12
Doc/library/functools.rst
Doc/library/functools.rst
+14
-1
Doc/whatsnew/3.8.rst
Doc/whatsnew/3.8.rst
+17
-0
Lib/functools.py
Lib/functools.py
+8
-4
Lib/test/test_functools.py
Lib/test/test_functools.py
+12
-7
Misc/NEWS.d/next/Library/2019-05-01-20-41-53.bpo-36772.fV2K0F.rst
...S.d/next/Library/2019-05-01-20-41-53.bpo-36772.fV2K0F.rst
+2
-0
No files found.
Doc/library/functools.rst
View file @
b821868e
...
...
@@ -76,7 +76,8 @@ The :mod:`functools` module defines the following functions:
.. versionadded:: 3.2
.. decorator:: lru_cache(maxsize=128, typed=False)
.. decorator:: lru_cache(user_function)
lru_cache(maxsize=128, typed=False)
Decorator to wrap a function with a memoizing callable that saves up to the
*maxsize* most recent calls. It can save time when an expensive or I/O bound
...
...
@@ -90,6 +91,15 @@ The :mod:`functools` module defines the following functions:
differ in their keyword argument order and may have two separate cache
entries.
If *user_function* is specified, it must be a callable. This allows the
*lru_cache* decorator to be applied directly to a user function, leaving
the *maxsize* at its default value of 128::
@lru_cache
def count_vowels(sentence):
sentence = sentence.casefold()
return sum(sentence.count(vowel) for vowel in 'aeiou')
If *maxsize* is set to ``None``, the LRU feature is disabled and the cache can
grow without bound. The LRU feature performs best when *maxsize* is a
power-of-two.
...
...
@@ -165,6 +175,9 @@ The :mod:`functools` module defines the following functions:
.. versionchanged:: 3.3
Added the *typed* option.
.. versionchanged:: 3.8
Added the *user_function* option.
.. decorator:: total_ordering
Given a class defining one or more rich comparison ordering methods, this
...
...
Doc/whatsnew/3.8.rst
View file @
b821868e
...
...
@@ -291,6 +291,23 @@ where the DLL is stored (if a full or partial path is used to load the initial
DLL) and paths added by :func:`~os.add_dll_directory`.
functools
---------
:func:`functools.lru_cache` can now be used as a straight decorator rather
than as a function returning a decorator. So both of these are now supported::
@lru_cache
def f(x):
...
@lru_cache(maxsize=256)
def f(x):
...
(Contributed by Raymond Hettinger in :issue:`36772`.)
datetime
--------
...
...
Lib/functools.py
View file @
b821868e
...
...
@@ -518,14 +518,18 @@ def lru_cache(maxsize=128, typed=False):
# The internals of the lru_cache are encapsulated for thread safety and
# to allow the implementation to change (including a possible C version).
# Early detection of an erroneous call to @lru_cache without any arguments
# resulting in the inner function being passed to maxsize instead of an
# integer or None. Negative maxsize is treated as 0.
if
isinstance
(
maxsize
,
int
):
# Negative maxsize is treated as 0
if
maxsize
<
0
:
maxsize
=
0
elif
callable
(
maxsize
)
and
isinstance
(
typed
,
bool
):
# The user_function was passed in directly via the maxsize argument
user_function
,
maxsize
=
maxsize
,
128
wrapper
=
_lru_cache_wrapper
(
user_function
,
maxsize
,
typed
,
_CacheInfo
)
return
update_wrapper
(
wrapper
,
user_function
)
elif
maxsize
is
not
None
:
raise
TypeError
(
'Expected maxsize to be an integer or None'
)
raise
TypeError
(
'Expected first argument to be an integer, a callable, or None'
)
def
decorating_function
(
user_function
):
wrapper
=
_lru_cache_wrapper
(
user_function
,
maxsize
,
typed
,
_CacheInfo
)
...
...
Lib/test/test_functools.py
View file @
b821868e
...
...
@@ -1251,6 +1251,18 @@ class TestLRU:
self
.
assertEqual
(
misses
,
4
)
self
.
assertEqual
(
currsize
,
2
)
def
test_lru_no_args
(
self
):
@
self
.
module
.
lru_cache
def
square
(
x
):
return
x
**
2
self
.
assertEqual
(
list
(
map
(
square
,
[
10
,
20
,
10
])),
[
100
,
400
,
100
])
self
.
assertEqual
(
square
.
cache_info
().
hits
,
1
)
self
.
assertEqual
(
square
.
cache_info
().
misses
,
2
)
self
.
assertEqual
(
square
.
cache_info
().
maxsize
,
128
)
self
.
assertEqual
(
square
.
cache_info
().
currsize
,
2
)
def
test_lru_bug_35780
(
self
):
# C version of the lru_cache was not checking to see if
# the user function call has already modified the cache
...
...
@@ -1582,13 +1594,6 @@ class TestLRU:
self
.
assertEqual
(
test_func
(
DoubleEq
(
2
)),
# Trigger a re-entrant __eq__ call
DoubleEq
(
2
))
# Verify the correct return value
def
test_early_detection_of_bad_call
(
self
):
# Issue #22184
with
self
.
assertRaises
(
TypeError
):
@
functools
.
lru_cache
def
f
():
pass
def
test_lru_method
(
self
):
class
X
(
int
):
f_cnt
=
0
...
...
Misc/NEWS.d/next/Library/2019-05-01-20-41-53.bpo-36772.fV2K0F.rst
0 → 100644
View file @
b821868e
functools.lru_cache() can now be used as a straight decorator in
addition to its existing usage as a function that returns a decorator.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment