0

I would like to access a Python function's return value multiple times without repeating the computationally expensive parts.

Example:

def expensive_function():
    print('do expensive work')
    return 'output of expensive work'


def get_output_twice():
    output = expensive_function()  # This does the expensive work
    print(output)  # This does not do expensive work
    print(output)  # This does not do expensive work


def get_output_again():
    output = expensive_function()  # This does the expensive work again
    print(output)  # This does not do expensive work


get_output_twice()
print('\n')
get_output_again()

This produces:

do expensive work
output of expensive work
output of expensive work

do expensive work
output of expensive work

This example demonstrates:

  1. Assigning the return value to a variable allows that variable to be accessed multiple times without calling the function again, as demonstrated in get_output_twice().
  2. Assigning the return value to a variable in another function forces the expensive function to be called again.

Is it possible to access a function's return value via calls from multiple other functions without repeating expensive work and without the use of global?

IslandPatrol
  • 261
  • 3
  • 11
  • 2
    If it's a _pure_ function, [memoize](https://en.wikipedia.org/wiki/Memoization) it. Note that the lines you've highlighted are _not_ where the work is done. – jonrsharpe Apr 16 '23 at 23:31
  • 1
    If you want to reuse a result instead of recomputing it then you have to store it *somewhere*. That doesn't have to be a global variable, as you've already demonstrated. Other options include ordinary variables of functions earlier in the call chain, closures, and class instances. However, all of these involve one way or another someone receiving the wanted value from one call and passing it on to other users. – John Bollinger Apr 16 '23 at 23:37
  • Updated the code to correct _where_ the "expensive work" is done and not done. – IslandPatrol Apr 16 '23 at 23:40

1 Answers1

3

Yes, you can use function caching to achieve this. Function caching is a technique where the result of an expensive function call is stored in memory and reused later when the function is called again with the same input.

from functools import lru_cache

@lru_cache(maxsize=None)
def expensive_function():
    print('do expensive work')
    return 'output of expensive work'

(maxsize=None indicates that the cache can grow indefinitely and cache all possible input-output pairs of the function).

Jabrove
  • 718
  • 5
  • 13
  • It appears that doing `import functools` followed by `@functools.cache` before the function definition also works in Python 3.9 and later. – IslandPatrol Apr 16 '23 at 23:51