Search code examples
pythonperformanceclassoop

How to avoid repeated calls of class method when it only needs to be executed once


Below is a snippet where I have lengthy calculation which I only want to perform once - because it takes a long time. I need to call this calculation repeatedly in other methods (in this example, only one - do_something_with_my_value).

Is there a way I can make my_value execute only once, and store the value down for the purposes of using it in do_something_with_my_value?

I could bind the return value of my_value in the function itself by manually setting a class attribute. But this would require the type hint to return None.

from typing import List


class Example:
    def __init__(self) -> None:
        pass

    def my_value(self) -> int:
        """Lenghthy calcultion, and so don't want to put in __init__"""
        return 1

    def do_something_with_my_value(self) -> List[int]:
        """Repeatedly uses my_value."""
        return [x + self.my_value() for x in range(1, 1000)]

I'm wondering if there's a "pythonic" design that avoid repeatedly doing a lengthy calculation as in the snippet above.

Many thanks for your help.


Solution

  • If my_value never changes throughout the life-cycle of your class then the functools.cached_property decorator is ideal:

    from functools import cached_property
    
    class Example:
    
        @cached_property
        def my_value(self) -> int:
            """Lengthy calculation goes here"""
            return 1
    
        def do_something_with_my_value(self) -> list[int]:
            """Note how my_value is accessed as a property rather than a function call"""
            return [x + self.my_value for x in range(1, 1000)]