@@ -146,31 +146,35 @@ def lru_cache(maxsize=100, typed=False):
146146 # The internals of the lru_cache are encapsulated for thread safety and
147147 # to allow the implementation to change (including a possible C version).
148148
149- def decorating_function (user_function ,
150- * , tuple = tuple , sorted = sorted , map = map , len = len , type = type ):
149+ def decorating_function (user_function ):
151150
152151 cache = dict ()
153152 hits = misses = 0
154- cache_get = cache .get # bound method for fast lookup
155- kwd_mark = (object (),) # separates positional and keyword args
156- lock = Lock () # needed because linkedlist isn't threadsafe
157- root = [] # root of circular doubly linked list
153+ cache_get = cache .get # bound method to lookup key or return None
154+ _len = len # localize the global len() function
155+ kwd_mark = (object (),) # separate positional and keyword args
156+ lock = Lock () # because linkedlist updates aren't threadsafe
157+ root = [] # root of the circular doubly linked list
158158 root [:] = [root , root , None , None ] # initialize by pointing to self
159- PREV , NEXT , KEY , RESULT = 0 , 1 , 2 , 3 # names of link fields
159+ PREV , NEXT , KEY , RESULT = 0 , 1 , 2 , 3 # names for the link fields
160+
161+ def make_key (args , kwds , typed , tuple = tuple , sorted = sorted , type = type ):
162+ key = args
163+ if kwds :
164+ sorted_items = tuple (sorted (kwds .items ()))
165+ key += kwd_mark + sorted_items
166+ if typed :
167+ key += tuple (type (v ) for v in args )
168+ if kwds :
169+ key += tuple (type (v ) for k , v in sorted_items )
170+ return key
160171
161172 if maxsize is None :
162173 @wraps (user_function )
163174 def wrapper (* args , ** kwds ):
164175 # simple caching without ordering or size limit
165176 nonlocal hits , misses
166- key = args
167- if kwds :
168- sorted_items = tuple (sorted (kwds .items ()))
169- key += kwd_mark + sorted_items
170- if typed :
171- key += tuple (map (type , args ))
172- if kwds :
173- key += tuple (type (v ) for k , v in sorted_items )
177+ key = make_key (args , kwds , typed ) if kwds or typed else args
174178 result = cache_get (key )
175179 if result is not None :
176180 hits += 1
@@ -184,14 +188,7 @@ def wrapper(*args, **kwds):
184188 def wrapper (* args , ** kwds ):
185189 # size limited caching that tracks accesses by recency
186190 nonlocal hits , misses
187- key = args
188- if kwds :
189- sorted_items = tuple (sorted (kwds .items ()))
190- key += kwd_mark + sorted_items
191- if typed :
192- key += tuple (map (type , args ))
193- if kwds :
194- key += tuple (type (v ) for k , v in sorted_items )
191+ key = make_key (args , kwds , typed ) if kwds or typed else args
195192 with lock :
196193 link = cache_get (key )
197194 if link is not None :
@@ -210,7 +207,7 @@ def wrapper(*args, **kwds):
210207 last = root [PREV ]
211208 link = [last , root , key , result ]
212209 cache [key ] = last [NEXT ] = root [PREV ] = link
213- if len (cache ) > maxsize :
210+ if _len (cache ) > maxsize :
214211 # purge least recently used cache entry
215212 old_prev , old_next , old_key , old_result = root [NEXT ]
216213 root [NEXT ] = old_next
@@ -229,7 +226,6 @@ def cache_clear():
229226 nonlocal hits , misses , root
230227 with lock :
231228 cache .clear ()
232- root = []
233229 root [:] = [root , root , None , None ]
234230 hits = misses = 0
235231
0 commit comments