Make a cache key from optionally typed positional and keyword arguments The key is constructed in a way that is flat as possible rather than as a nested structure that would take more memory. If there is only a single argument and its data type is known to cache its hash value, the
(args, kwds, typed,
kwd_mark = (object(),),
fasttypes = {int, str},
tuple=tuple, type=type, len=len)
| 520 | _CacheInfo = namedtuple("CacheInfo", ("hits", "misses", "maxsize", "currsize")) |
| 521 | |
| 522 | def _make_key(args, kwds, typed, |
| 523 | kwd_mark = (object(),), |
| 524 | fasttypes = {int, str}, |
| 525 | tuple=tuple, type=type, len=len): |
| 526 | """Make a cache key from optionally typed positional and keyword arguments |
| 527 | |
| 528 | The key is constructed in a way that is flat as possible rather than |
| 529 | as a nested structure that would take more memory. |
| 530 | |
| 531 | If there is only a single argument and its data type is known to cache |
| 532 | its hash value, then that argument is returned without a wrapper. This |
| 533 | saves space and improves lookup speed. |
| 534 | |
| 535 | """ |
| 536 | # All of code below relies on kwds preserving the order input by the user. |
| 537 | # Formerly, we sorted() the kwds before looping. The new way is *much* |
| 538 | # faster; however, it means that f(x=1, y=2) will now be treated as a |
| 539 | # distinct call from f(y=2, x=1) which will be cached separately. |
| 540 | key = args |
| 541 | if kwds: |
| 542 | key = list(key) |
| 543 | key += kwd_mark |
| 544 | for item in kwds.items(): |
| 545 | key += item |
| 546 | key = tuple(key) |
| 547 | if typed: |
| 548 | key += tuple([type(v) for v in args]) |
| 549 | if kwds: |
| 550 | key += tuple([type(v) for v in kwds.values()]) |
| 551 | elif len(key) == 1 and type(key[0]) in fasttypes: |
| 552 | return key[0] |
| 553 | return key |
| 554 | |
| 555 | def lru_cache(maxsize=128, typed=False): |
| 556 | """Least-recently-used cache decorator. |