xref: /aosp_15_r20/external/emboss/compiler/util/simple_memoizer.py (revision 99e0aae7469b87d12f0ad23e61142c2d74c1ef70)
1# Copyright 2019 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Provides a simple memoizing decorator."""
16
17
18def memoize(f):
19  """Memoizes f.
20
21  The @memoize decorator returns a function which caches the results of f, and
22  returns directly from the cache instead of calling f when it is called again
23  with the same arguments.
24
25  Memoization has some caveats:
26
27  Most importantly, the decorated function will not be called every time the
28  function is called.  If the memoized function `f` performs I/O or relies on
29  or changes global state, it may not work correctly when memoized.
30
31  This memoizer only works for functions taking positional arguments.  It does
32  not handle keywork arguments.
33
34  This memoizer only works for hashable arguments -- tuples, ints, etc.  It does
35  not work on most iterables.
36
37  This memoizer returns a function whose __name__ and argument list may differ
38  from the memoized function under reflection.
39
40  This memoizer never evicts anything from its cache, so its memory usage can
41  grow indefinitely.
42
43  Depending on the workload and speed of `f`, the memoized `f` can be slower
44  than unadorned `f`; it is important to use profiling before and after
45  memoization.
46
47  Usage:
48      @memoize
49      def function(arg, arg2, arg3):
50         ...
51
52  Arguments:
53      f: The function to memoize.
54
55  Returns:
56      A function which acts like f, but faster when called repeatedly with the
57      same arguments.
58  """
59  cache = {}
60
61  def _memoized(*args):
62    assert all(arg.__hash__ for arg in args), (
63        "Arguments to memoized function {} must be hashable.".format(
64            f.__name__))
65    if args not in cache:
66      cache[args] = f(*args)
67    return cache[args]
68
69  return _memoized
70