Reputation: 1442
I have a class as such:
class Line:
def __init__(self, text: str):
self.text = text
A line in my case can have many features
. For example,
I am able to implement them in terms of class methods:
class Line:
def __init__(self, text: str):
self.text = text
def is_ascii(self):
# check and return
def is_long(self):
# check and return
def urls(self):
# find and return urls
The problem I have is, I need to make the method calls on the Line object multiple times at different stages in the process (some of the method calls are pretty computationally heavy).
What I would like to have is, at initialization, I would like the Line object to have attributes such as is_ascii, is_long, urls to be pre populated so that they can be accessed multiple times without the need to compute them every time they are accessed.
class Line:
def __init__(self, text: str):
self.text = text
self.is_ascii = do some processing on self.text, and assign value
self.is_long = do some processing on self.text, and assign value
self.urls = do some processing on self.text, and assign value
I am not sure if having all that logic live inside the init block makes sense. How would I achieve this in a 'pythonic' manner?
Upvotes: 1
Views: 843
Reputation: 45750
You could just have the methods that you do, and call them from within __init__
:
class Line:
def __init__(self, text: str):
self.text = text
self.is_ascii = self.calc_is_ascii(self.text)
self.is_long = self.calc_is_long(self.text)
self.urls = self.calc_urls(self.text)
def calc_is_ascii(self):
# check and return
def calc_is_long(self):
# check and return
def calc_urls(self):
# find and return urls
You could also have it so if a method is called, it checks to see if the value has already been calculated, and uses the cached value, otherwise it calculates and caches it:
class Line:
def __init__(self, text: str):
self.text = text
self.is_ascii = None
self.is_long = None
self.urls = None
def calc_is_ascii(self):
if self.is_ascii is None:
# Do expensive calculation of self.is_ascii
self.is_ascii = expensive_result
# Use the cached, previously calculated value
return self.is_ascii
# Then the same pattern for other methods
This has the benefit that if one of the attributes is never needed, the work to calculate it isn't done.
I'm initializing the attributes to None
. If they're None
later, I know they haven't been calculated yet. If they aren't None
, I know they have already been calculated, so I can just return the calculated result. This of course assumes that None
is not a valid value.
Upvotes: 2