[Python-checkins] r86901 - in python/branches/py3k: Doc/library/functools.rst Doc/whatsnew/3.2.rst Lib/functools.py Lib/test/test_functools.py

raymond.hettinger python-checkins at python.org
Tue Nov 30 20:15:45 CET 2010


Author: raymond.hettinger
Date: Tue Nov 30 20:15:45 2010
New Revision: 86901
Log:
Add example, tighten text, and minor clean-ups.
Modified:
 python/branches/py3k/Doc/library/functools.rst
 python/branches/py3k/Doc/whatsnew/3.2.rst
 python/branches/py3k/Lib/functools.py
 python/branches/py3k/Lib/test/test_functools.py
Modified: python/branches/py3k/Doc/library/functools.rst
==============================================================================
--- python/branches/py3k/Doc/library/functools.rst	(original)
+++ python/branches/py3k/Doc/library/functools.rst	Tue Nov 30 20:15:45 2010
@@ -42,40 +42,52 @@
 .. versionadded:: 3.2
 
 
-.. decorator:: lru_cache(maxsize)
+.. decorator:: lru_cache(maxsize=100)
 
 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
 function is periodically called with the same arguments.
 
- The *maxsize* parameter defaults to 100. Since a dictionary is used to cache
- results, the positional and keyword arguments to the function must be
- hashable.
-
- The wrapped function is instrumented with a :attr:`cache_info` attribute that
- can be called to retrieve a named tuple with the following fields:
-
- - :attr:`maxsize`: maximum cache size (as set by the *maxsize* parameter)
- - :attr:`size`: current number of entries in the cache
- - :attr:`hits`: number of successful cache lookups
- - :attr:`misses`: number of unsuccessful cache lookups.
+ Since a dictionary is used to cache results, the positional and keyword
+ arguments to the function must be hashable.
 
- These statistics are helpful for tuning the *maxsize* parameter and for measuring
- the effectiveness of the cache.
+ To help measure the effectiveness of the cache and tune the *maxsize*
+ parameter, the wrapped function is instrumented with a :func:`cache_info`
+ function that returns a :term:`named tuple` showing *hits*, *misses*,
+ *maxsize* and *currsize*.
 
- The wrapped function also has a :attr:`cache_clear` attribute which can be
- called (with no arguments) to clear the cache.
+ The decorator also provides a :func:`cache_clear` function for clearing or
+ invalidating the cache.
 
 The original underlying function is accessible through the
- :attr:`__wrapped__` attribute. This allows introspection, bypassing
- the cache, or rewrapping the function with a different caching tool.
+ :attr:`__wrapped__` attribute. This is useful for introspection, for
+ bypassing the cache, or for rewrapping the function with a different cache.
 
 A `LRU (least recently used) cache
- <http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used>`_
- works best when more recent calls are the best predictors of upcoming calls
- (for example, the most popular articles on a news server tend to
- change each day). The cache's size limit assurs that caching does not
- grow without bound on long-running processes such as web servers.
+ <http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used>`_ works
+ best when more recent calls are the best predictors of upcoming calls (for
+ example, the most popular articles on a news server tend to change daily).
+ The cache's size limit assures that the cache does not grow without bound on
+ long-running processes such as web servers.
+
+ Example -- Caching static web content::
+
+ @functools.lru_cache(maxsize=20)
+ def get_pep(num):
+ 'Retrieve text of a Python Enhancement Proposal'
+ resource = 'http://www.python.org/dev/peps/pep-%04d/' % num
+ try:
+ with urllib.request.urlopen(resource) as s:
+ return s.read()
+ except urllib.error.HTTPError:
+ return 'Not Found'
+
+ >>> for n in 8, 290, 308, 320, 8, 218, 320, 279, 289, 320, 9991:
+ ... pep = get_pep(n)
+ ... print(n, len(pep))
+
+ >>> print(get_pep.cache_info())
+ CacheInfo(hits=3, misses=8, maxsize=20, currsize=8)
 
 .. versionadded:: 3.2
 
Modified: python/branches/py3k/Doc/whatsnew/3.2.rst
==============================================================================
--- python/branches/py3k/Doc/whatsnew/3.2.rst	(original)
+++ python/branches/py3k/Doc/whatsnew/3.2.rst	Tue Nov 30 20:15:45 2010
@@ -332,13 +332,14 @@
 c.execute('SELECT phonenumber FROM phonelist WHERE name=?', (name,))
 return c.fetchone()[0]
 
+ >>> for name in user_requests:
+ ... get_phone_number(name) # cached lookup
+
 To help with choosing an effective cache size, the wrapped function is
- instrumented with info function:
+ instrumented for tracking cache statistics:
 
- >>> for name in user_requests:
- ... get_phone_number(name)
 >>> get_phone_number.cache_info()
- CacheInfo(maxsize=300, size=300, hits=4805, misses=980)
+ CacheInfo(hits=4805, misses=980, maxsize=300, currsize=300)
 
 If the phonelist table gets updated, the outdated contents of the cache can be
 cleared with:
Modified: python/branches/py3k/Lib/functools.py
==============================================================================
--- python/branches/py3k/Lib/functools.py	(original)
+++ python/branches/py3k/Lib/functools.py	Tue Nov 30 20:15:45 2010
@@ -114,7 +114,7 @@
 raise TypeError('hash not implemented')
 return K
 
-_CacheInfo = namedtuple("CacheInfo", "maxsize, size, hits, misses")
+_CacheInfo = namedtuple("CacheInfo", "hits misses maxsize currsize")
 
 def lru_cache(maxsize=100):
 """Least-recently-used cache decorator.
@@ -166,7 +166,7 @@
 def cache_info():
 """Report cache statistics"""
 with lock:
- return _CacheInfo(maxsize, len(cache), hits, misses)
+ return _CacheInfo(hits, misses, maxsize, len(cache))
 
 def cache_clear():
 """Clear the cache and cache statistics"""
Modified: python/branches/py3k/Lib/test/test_functools.py
==============================================================================
--- python/branches/py3k/Lib/test/test_functools.py	(original)
+++ python/branches/py3k/Lib/test/test_functools.py	Tue Nov 30 20:15:45 2010
@@ -501,7 +501,7 @@
 def orig(x, y):
 return 3*x+y
 f = functools.lru_cache(maxsize=20)(orig)
- maxsize, currsize, hits, misses = f.cache_info()
+ hits, misses, maxsize, currsize = f.cache_info()
 self.assertEqual(maxsize, 20)
 self.assertEqual(currsize, 0)
 self.assertEqual(hits, 0)
@@ -513,18 +513,18 @@
 actual = f(x, y)
 expected = orig(x, y)
 self.assertEqual(actual, expected)
- maxsize, currsize, hits, misses = f.cache_info()
+ hits, misses, maxsize, currsize = f.cache_info()
 self.assertTrue(hits > misses)
 self.assertEqual(hits + misses, 1000)
 self.assertEqual(currsize, 20)
 
 f.cache_clear() # test clearing
- maxsize, currsize, hits, misses = f.cache_info()
+ hits, misses, maxsize, currsize = f.cache_info()
 self.assertEqual(hits, 0)
 self.assertEqual(misses, 0)
 self.assertEqual(currsize, 0)
 f(x, y)
- maxsize, currsize, hits, misses = f.cache_info()
+ hits, misses, maxsize, currsize = f.cache_info()
 self.assertEqual(hits, 0)
 self.assertEqual(misses, 1)
 self.assertEqual(currsize, 1)
@@ -532,7 +532,7 @@
 # Test bypassing the cache
 self.assertIs(f.__wrapped__, orig)
 f.__wrapped__(x, y)
- maxsize, currsize, hits, misses = f.cache_info()
+ hits, misses, maxsize, currsize = f.cache_info()
 self.assertEqual(hits, 0)
 self.assertEqual(misses, 1)
 self.assertEqual(currsize, 1)
@@ -548,7 +548,7 @@
 for i in range(5):
 self.assertEqual(f(), 20)
 self.assertEqual(f_cnt, 5)
- maxsize, currsize, hits, misses = f.cache_info()
+ hits, misses, maxsize, currsize = f.cache_info()
 self.assertEqual(hits, 0)
 self.assertEqual(misses, 5)
 self.assertEqual(currsize, 0)
@@ -564,7 +564,7 @@
 for i in range(5):
 self.assertEqual(f(), 20)
 self.assertEqual(f_cnt, 1)
- maxsize, currsize, hits, misses = f.cache_info()
+ hits, misses, maxsize, currsize = f.cache_info()
 self.assertEqual(hits, 4)
 self.assertEqual(misses, 1)
 self.assertEqual(currsize, 1)
@@ -581,7 +581,7 @@
 # * * * *
 self.assertEqual(f(x), x*10)
 self.assertEqual(f_cnt, 4)
- maxsize, currsize, hits, misses = f.cache_info()
+ hits, misses, maxsize, currsize = f.cache_info()
 self.assertEqual(hits, 12)
 self.assertEqual(misses, 4)
 self.assertEqual(currsize, 2)


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /