在 python class 中实施不断变化的业务逻辑
Implement changing business logic in python class
我想在python中实现一个经常发生变化的业务逻辑。更新此业务逻辑应该很容易,并且应保留旧逻辑。
我目前的想法是这样的:
class Item():
def __init__(self):
pass
def __call__(self, company, time):
if time < "2017Q1":
return self.calc_base(company, time)
elif time < "2018Q2":
return self.calc_after2017Q1
else:
return self.calc_after2018Q2
def calc_base(self, company, time):
return income(company, time) + costs(company, time)
@time_after("2017Q1")
def calc_after2017Q1(self, company, time):
intermediate = self.calc_base(company, time)
return max(intermediate, 100_000) #Haircutt due to article xxx
@time_after("2018Q2")
def calc_after2018Q2(self, company, time):
intermediate = self.calc_after2017Q1(company, time)
intermediate -= 20_000 #Correction due to xxx
我们的想法是调用此 class 的实例,并将公司和时间作为参数。在内部,class 会查看当时要使用哪个业务逻辑,然后它会路由到正确的计算函数。每当逻辑发生变化时,只需添加一个新函数并记录它与以前的计算有何不同。
此实现需要对 self.call 函数中的 if .. elif .. else 进行相当多的管理。谁能想出一个 pythonic 和智能的自动化方法?我在考虑装饰器的思路(如本示例中所示,但未实现),我可以在其中指定新逻辑从哪个时间开始有效,直到下一个逻辑取代它。
最后,我觉得我在这里重新发明轮子,因为这可能是一个非常标准的问题。但不知何故,我似乎缺乏正确的词汇来在这个方向上找到好的结果。因此,我也很感激正确方向的提示。
好吧,更多的 OOP 方法是使用抽象 class 来定义基本计算函数。将 After201Q1
创建为 class 从这个抽象 class 扩展并实现 calc
函数。然后创建 After2018Q2
as class extending from After201Q1
然后写一个 factory
函数来得到基于那个时间的实现。我不认为比较时间小于字符串是正确的方法。我认为,直接对其进行索引是一种正确的方法。我创建了一个示例代码。代码大部分看起来像下面的代码。但是,您可能需要根据需要进行少量修改。但是我已经展示了一个基本的想法。
from abc import ABC, abstractmethod
from collections import OrderedDict
def income(*args):
return 1
def costs(*args):
return 2
# Abstract class
class Item(ABC):
def calc_base(self, company, time):
print('Base calc_base')
return income(company, time) + costs(company, time)
def calc(self, company, time):
print('Base calc')
intermediate = self.calc_base(company, time)
return self.calc_specific(intermediate, time)
@abstractmethod
def calc_specific(self, company, time):
pass
class After2017Q1(Item):
def calc_specific(self, company, time):
print('Running After2017Q1')
return max(company, 100000) # Haircutt due to article xxx
class After2018Q2(After2017Q1):
def calc_specific(self, company, time):
print('Running After2018Q2')
intermediate = super().calc_specific(company, time)
return intermediate - 20000
def factory(time):
object_factory = OrderedDict([
('2017Q1', After2017Q1()),
('2018Q2', After2018Q2())
])
return object_factory[time]
print(factory('2017Q1').calc(None, None))
print('-'*20)
print(factory('2018Q2').calc(None, None))
你可以添加任意数量的子classes,只写calc_specific
函数,然后将它添加到工厂函数中,这样它就会根据时间值被调用。
我想在python中实现一个经常发生变化的业务逻辑。更新此业务逻辑应该很容易,并且应保留旧逻辑。
我目前的想法是这样的:
class Item():
def __init__(self):
pass
def __call__(self, company, time):
if time < "2017Q1":
return self.calc_base(company, time)
elif time < "2018Q2":
return self.calc_after2017Q1
else:
return self.calc_after2018Q2
def calc_base(self, company, time):
return income(company, time) + costs(company, time)
@time_after("2017Q1")
def calc_after2017Q1(self, company, time):
intermediate = self.calc_base(company, time)
return max(intermediate, 100_000) #Haircutt due to article xxx
@time_after("2018Q2")
def calc_after2018Q2(self, company, time):
intermediate = self.calc_after2017Q1(company, time)
intermediate -= 20_000 #Correction due to xxx
我们的想法是调用此 class 的实例,并将公司和时间作为参数。在内部,class 会查看当时要使用哪个业务逻辑,然后它会路由到正确的计算函数。每当逻辑发生变化时,只需添加一个新函数并记录它与以前的计算有何不同。
此实现需要对 self.call 函数中的 if .. elif .. else 进行相当多的管理。谁能想出一个 pythonic 和智能的自动化方法?我在考虑装饰器的思路(如本示例中所示,但未实现),我可以在其中指定新逻辑从哪个时间开始有效,直到下一个逻辑取代它。
最后,我觉得我在这里重新发明轮子,因为这可能是一个非常标准的问题。但不知何故,我似乎缺乏正确的词汇来在这个方向上找到好的结果。因此,我也很感激正确方向的提示。
好吧,更多的 OOP 方法是使用抽象 class 来定义基本计算函数。将 After201Q1
创建为 class 从这个抽象 class 扩展并实现 calc
函数。然后创建 After2018Q2
as class extending from After201Q1
然后写一个 factory
函数来得到基于那个时间的实现。我不认为比较时间小于字符串是正确的方法。我认为,直接对其进行索引是一种正确的方法。我创建了一个示例代码。代码大部分看起来像下面的代码。但是,您可能需要根据需要进行少量修改。但是我已经展示了一个基本的想法。
from abc import ABC, abstractmethod
from collections import OrderedDict
def income(*args):
return 1
def costs(*args):
return 2
# Abstract class
class Item(ABC):
def calc_base(self, company, time):
print('Base calc_base')
return income(company, time) + costs(company, time)
def calc(self, company, time):
print('Base calc')
intermediate = self.calc_base(company, time)
return self.calc_specific(intermediate, time)
@abstractmethod
def calc_specific(self, company, time):
pass
class After2017Q1(Item):
def calc_specific(self, company, time):
print('Running After2017Q1')
return max(company, 100000) # Haircutt due to article xxx
class After2018Q2(After2017Q1):
def calc_specific(self, company, time):
print('Running After2018Q2')
intermediate = super().calc_specific(company, time)
return intermediate - 20000
def factory(time):
object_factory = OrderedDict([
('2017Q1', After2017Q1()),
('2018Q2', After2018Q2())
])
return object_factory[time]
print(factory('2017Q1').calc(None, None))
print('-'*20)
print(factory('2018Q2').calc(None, None))
你可以添加任意数量的子classes,只写calc_specific
函数,然后将它添加到工厂函数中,这样它就会根据时间值被调用。