How to optimize a frequently read method in a python class?
Question:
There are many methods defined in MyClass
that needs to call read_my_obj
, is the code below a good way to avoid re-creating a new MyObjectType instance every time to save memory and improve execution speed? Or is there a more pythonic way to do achieve this type of pattern?
class MyClass:
my_obj: Optional[MyObjectType] = None
@classmethod
def read_my_obj(cls) -> MyObjectType:
if cls.my_obj is not None:
return cls.my_obj # treating my_obj as a singleton, to avoid instantiating a new one each time
obj_field = read_from_db()
cls.my_obj = MyObjectType(obj_field) # instantiate my object for first time
return cls.my_obj
Answers:
I would use a hidden attribute + property to achieve "run-time" caching of instantiated objects:
class MyClass:
def __init__(self):
self._my_obj = None # hidden attribute begins with an underscore
@property
def my_obj(self): -> MyObjectType
# Create if not exists
if not self._my_obj:
obj_field = read_from_db()
self._my_obj = MyObjectType(obj_field)
# return hidden attribute
return self._my_obj
Do note that this hidden attribute will only get populated once per class instance (on accessing property). If you need more frequent refreshes, you could configure some datetime logic within the property.
There are many methods defined in MyClass
that needs to call read_my_obj
, is the code below a good way to avoid re-creating a new MyObjectType instance every time to save memory and improve execution speed? Or is there a more pythonic way to do achieve this type of pattern?
class MyClass:
my_obj: Optional[MyObjectType] = None
@classmethod
def read_my_obj(cls) -> MyObjectType:
if cls.my_obj is not None:
return cls.my_obj # treating my_obj as a singleton, to avoid instantiating a new one each time
obj_field = read_from_db()
cls.my_obj = MyObjectType(obj_field) # instantiate my object for first time
return cls.my_obj
I would use a hidden attribute + property to achieve "run-time" caching of instantiated objects:
class MyClass:
def __init__(self):
self._my_obj = None # hidden attribute begins with an underscore
@property
def my_obj(self): -> MyObjectType
# Create if not exists
if not self._my_obj:
obj_field = read_from_db()
self._my_obj = MyObjectType(obj_field)
# return hidden attribute
return self._my_obj
Do note that this hidden attribute will only get populated once per class instance (on accessing property). If you need more frequent refreshes, you could configure some datetime logic within the property.