Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python method which computes the result only on the first call, without extra parameters

Is there an idiomatic way to implement an "once method", that is: a method whose return value gets evaluated on the first call only? Something like what the following simplified code does for the return value of x:

class X:
    def __init__(self):
        self._x = None

    def x(self):
        if not self._x:
            self._x = some_expensive_call()
        return self._x
like image 267
Eleno Avatar asked Feb 14 '16 01:02

Eleno


People also ask

How do you call a function without an argument in Python?

7.1. Functions do not have declared return types. A function without an explicit return statement returns None . In the case of no arguments and no return value, the definition is very simple. Calling the function is performed by using the call operator () after the name of the function.

What is call method in Python?

Call a method of the Python object obj, where the name of the method is given as a Python string object in name. It is called with a variable number of PyObject* arguments. The arguments are provided as a variable number of parameters followed by NULL.

How do you return nothing from a function in Python?

In Python, it is possible to compose a function without a return statement. Functions like this are called void, and they return None, Python's special object for "nothing". Here's an example of a void function: >>> def sayhello(who): print 'Hello,', who + '!'

How do you print the results of a function in Python?

To print the output of a function: Make sure to return a value from the function. Call the function and store the result in a variable. Use the print() function to print the result.


1 Answers

As of Python 3.2, you can use the functools.lru_cache decorator (but it may be overkill for what you need):

import functools

@functools.lru_cache(maxsize=1)
def once():
    print("calculating expensive result")
    return "expensive result"

once()
once()

output:

calculating expensive result         # <- only prints on first call
'expensive result'                   # returned value on first call
'expensive result'                   # <- just return value on second call

Alternatively, you can write your own decorator:

def cache_result(func):
    def wrapper(*args, **kwds):
        if not wrapper.cached:
            wrapper.value = func(*args, **kwds)
            wrapper.cached = True

        return wrapper.value

    wrapper.cached = False

    return functools.update_wrapper(wrapper, func)

And use it on any function you want to run only once and cache the result

@cache_result
def do_once():
    print('doing it once')
    return 'expensive result'
like image 197
RootTwo Avatar answered Nov 02 '22 23:11

RootTwo