1

My problem simplified:

Let's assume that method_1 is a computationally heavy function. There's a possibility that it won't be necessary to call it at all when working with the instance of the class (so I don't want to put it in the inside the init-function). Then there is the other possibility that method_2 will be called multiple times and with my current solution in that case every time also the method_1 is called.

What would be easiest and most pythonic solution?

class MyClass:
   def __init__(self, x, y):
      self.__x = x
      self.__y = y

   def method_1(self)
      # method that returns list which values vary depending on x and y
      return some_list


   def method_2(self, a)
      # method that modifies and returns specific list element from some_list according to a
      return do_modifications(self.method_1(), a)


   def method_3(self, arg1, ...)
      #some method
   ...
matthias_h
  • 11,356
  • 9
  • 22
  • 40
walter
  • 51
  • 1
  • 3
  • 1
    Not sure if this is the most pythonic but a possible solution is to save the list as a member of the class and then before method_2 calls method one it could check if the list already has a value, If its empty call method one if not use the saved list – barbecu Mar 19 '20 at 17:16
  • 2
    Use [memoization](https://en.wikipedia.org/wiki/Memoization). – Tom Karzes Mar 19 '20 at 17:17
  • As a side note, there is really no reason to be using double underscores in your attribute names here. See [this question](https://stackoverflow.com/questions/1641219/does-python-have-private-variables-in-classes) for more information on why this is not a good practice in Python. – Brian61354270 Mar 19 '20 at 17:22
  • Just like @TomKarzes mentioned the caching data that you will reuse would be the most pythoninc way of doing things. – Sergey Mar 19 '20 at 17:37

2 Answers2

3

If you're using Python 3.8, you can use functools.cache_property:

@functools.cached_property(func)

Transform a method of a class into a property whose value is computed once and then cached as a normal attribute for the life of the instance. Similar to property(), with the addition of caching. Useful for expensive computed properties of instances that are otherwise effectively immutable.

Brian61354270
  • 8,690
  • 4
  • 21
  • 43
1

Make method1's return value a property. (This is basically what functools.cached_property does; use that if possible.)

class MyClass:
   def __init__(self, x, y):
      self.x = x
      self.y = y
      self._m1_data = None

   def _method1(self):
       return some_list

   # Call _method1 on demand the first time you need
   # the result of self._method1(), and save the result for future
   # accesses
   @property
   def m1_data(self)
      if self._m1_data is None:
          self._m1_data = self._method1()
      return self._m1_data


   def method_2(self, a)
      return do_modifications(self.m1_data, a)
chepner
  • 497,756
  • 71
  • 530
  • 681