Posts: 11
Threads: 3
Joined: Jun 2020
Hi there,
I've defined an attribute, wave_coef, with the property decorator. It is a function of other attributes. Is there any way to store this value and not have it calculated each time I call it? And a way so the the object knows when the inputs have been changed and update the value?
class Vessel():
def __init__(self, class_notation, length):
self.class_notation = class_notation
self.length = length
@property
def wave_coef(self):
table = {"R0" : 1,
"R1" : 0.9,
"R2" : 0.8,
"R3" : 0.7,
"R4" : 0.6,
"R5" : 0.5,
"R6" : 0.4}
service_factor = table[self.class_notation]
if (self.length <= 100):
CW = 0.08 * self.length * service_factor
else:
CW = 6 + 0.02 * self.length * service_factor
return CW
Thanks
Posts: 8,167
Threads: 160
Joined: Sep 2016
Jun-09-2020, 04:27 PM
(This post was last modified: Jun-09-2020, 04:28 PM by buran.)
this will require to have setter for both length and class_notation and update the [internal] variable that will hold wave_coef whenever each of these these attributes change. And will be more open to [possible] errors.
In my opinion what you have now is better.
Posts: 2,168
Threads: 35
Joined: Sep 2016
Jun-09-2020, 04:34 PM
(This post was last modified: Jun-09-2020, 04:35 PM by Yoriz.)
It would look something like this
class Vessel():
def __init__(self, class_notation, length):
self._class_notation = class_notation
self._length = length
self.table = {"R0": 1,
"R1": 0.9,
"R2": 0.8,
"R3": 0.7,
"R4": 0.6,
"R5": 0.5,
"R6": 0.4}
self._wave_coef = 0
self.calc_wave_coef()
@property
def wave_coef(self):
return self._wave_coef
def calc_wave_coef(self):
print('calculating wave_coef')
service_factor = self.table[self._class_notation]
if (self.length <= 100):
CW = 0.08 * self._length * service_factor
else:
CW = 6 + 0.02 * self._length * service_factor
self._wave_coef = CW
@property
def class_notation(self):
return self._wave_coef
@class_notation.setter
def class_notation(self, value):
self._class_notation = value
self.calc_wave_coef()
@property
def length(self):
return self._length
@length.setter
def length(self, value):
self._length = value
self.calc_wave_coef()
vessel = Vessel('R2', 2)
print(vessel.wave_coef)
print(vessel.wave_coef)
vessel.class_notation = 'R4'
print(vessel.wave_coef)
vessel.length = 1
print(vessel.wave_coef) Output: calculating wave_coef
0.128
0.128
calculating wave_coef
0.096
calculating wave_coef
0.048
Posts: 2,168
Threads: 35
Joined: Sep 2016
Another way, keep track of the previous values, only re calculate if they have changed.
class Vessel():
def __init__(self, class_notation, length):
self.class_notation = class_notation
self.length = length
self.previous_values = (None, None, None)
@property
def wave_coef(self):
if self.previous_values[:2] == (self.class_notation, self.length):
return self.previous_values[2]
print('calculating wave_coef')
table = {"R0": 1,
"R1": 0.9,
"R2": 0.8,
"R3": 0.7,
"R4": 0.6,
"R5": 0.5,
"R6": 0.4}
service_factor = table[self.class_notation]
if (self.length <= 100):
CW = 0.08 * self.length * service_factor
else:
CW = 6 + 0.02 * self.length * service_factor
self.previous_values = (self.class_notation, self.length, CW)
return CW
vessel = Vessel('R2', 2)
print(vessel.wave_coef)
print(vessel.wave_coef)
vessel.class_notation = 'R4'
print(vessel.wave_coef)
vessel.length = 1
print(vessel.wave_coef) Output: calculating wave_coef
0.128
0.128
calculating wave_coef
0.096
calculating wave_coef
0.048
Posts: 11
Threads: 3
Joined: Jun 2020
Jun-09-2020, 04:57 PM
(This post was last modified: Jun-09-2020, 04:57 PM by ruy.)
Thanks a lot everyone.
(Jun-09-2020, 04:02 PM)buran Wrote: In my opinion what you have now is better.
I guess I can see why you would say so. The first code is much more simple and straightforward
Posts: 2,168
Threads: 35
Joined: Sep 2016
My last version, keeping track of the previous values is the better way to go, simpler and doesn't calculate when not necessary.
Posts: 8,167
Threads: 160
Joined: Sep 2016
Jun-09-2020, 05:29 PM
(This post was last modified: Jun-09-2020, 05:29 PM by buran.)
(Jun-09-2020, 04:57 PM)ruy Wrote: I guess I can see why you would say so. The first code is much more simple and straightforward yes + I don't think performance benefit of not calculating every time would be worth it. Second proposal by @Yoriz is fair compromise, but still it's open to mishandling if Vessel.previous_values property is changed by mistake.
EDIT: actually, yes, second proposal by @ Yoriz is better compromise
|