对齐 Python Class & 超-Class
Aligning Python Class & Super-Class
考虑以下 Python 代码片段,我们在其中定义了 Portfolio
、Company
和 Deposit
class。 Portfolio
对象只是充当公司和存款的联合体。我们可以 运行 投资组合的指标,例如 Profit
。问题:
对于我在 Company
或 Deposit
class 中包含的每个新指标,我需要在 Portfolio
class;尽管他们的行为始终相同:对所有投资求和。有没有办法改进 logic/construction of classes? 如果我们需要添加 100 个其他指标怎么办...
Deposit
class只有Profit
的功能,没有Loss
的功能(假定银行账户利息有保障) .有没有办法将 "undefined" 指标视为始终返回 0?或者是否有 cleaner/more 正确定义这些指标? 如果我们需要涵盖 100 种可能有或可能没有不同指标的不同投资类型怎么办...
class Company():
def __init__(self, ItemsSold, ItemPrice, Expenses, Fines):
self.ItemsSold = ItemsSold
self.ItemPrice = ItemPrice
self.Expenses = Expenses
self.Fines = Fines
def Profit(self):
return self.ItemsSold * self.ItemPrice
def Loss(self):
return self.Expenses + self.Fines
def ProfitAndLoss(self):
return self.Profit() - self.Loss()
class Portfolio():
def __init__(self, Investments):
self.Investments = Investments
def Profit(self):
return sum([inv.Profit() for inv in self.Investments])
def Loss(self):
return sum([inv.Loss() for inv in self.Investments])
def ProfitAndLoss(self):
return sum([inv.ProfitAndLoss() for inv in self.Investments])
class Deposit():
def __init__(self, Notional, InterestRate, TimeHorizon):
self.Notional = Notional
self.InterestRate = InterestRate
self.TimeHorizon = TimeHorizon
def Profit(self):
return self.Notional * self.InterestRate * self.TimeHorizon
myComp1 = Company(100,2,50,20)
myComp2 = Company(200,2,100,80)
myDepos = Deposit(100,0.02,3)
myPortf = Portfolio([myComp1,myComp2,myDepos])
print(myPortf.Profit()) # Works fine
print(myPortf.ProfitAndLoss()) # Throws an error
第二个问题很简单:您所要做的就是创建一个 Base
class,其中每个指标都定义为返回 0 的方法。然后派生所有 Invest
classes (Company
, Deposit
, etc) 来自 Base
class,因此所有未定义的指标将调用 [=12= 中的相应方法] class.
第一个问题有点难,因为它需要 meta-programming。你的Portfolio
class也可以从Base
class派生出来,然后在Base
class的方法字典中查找(Base.__dict__
) 检索所有指标名称。之后,对于所有这些指标,它会创建一个特定的 lambda 方法,该方法会为 Investments
列表中的每个项目调用此指标并对结果求和。这是一个框架代码:
class Base(object):
def f1(self):
return 0
def f2(self):
return 0
class InvestA(Base):
def f2(self):
return 2
class InvestB(Base):
def f1(self):
return 1
class Portfolio(Base):
def __init__(self, invest):
self.invest = invest
for name in [n for n in Base.__dict__ if n[:2] != '__']:
self.__dict__[name] = lambda name=name: self.sum(name)
def sum(self, name):
return sum([i.__class__.__dict__[name](i) for i in self.invest
if name in i.__class__.__dict__])
A = InvestA()
print("A.f1 = %s, A.f2 = %s" % (A.f1(), A.f2()))
B = InvestB()
print("B.f1 = %s, B.f2 = %s" % (B.f1(), B.f2()))
P = Portfolio([A,A,B])
print('P.f1 = A.f1 + A.f1 + B.f1 =', P.f1())
print('P.f2 = A.f2 + A.f2 + B.f2 =', P.f2())
产生以下输出:
A.f1 = 0, A.f2 = 2
B.f1 = 1, B.f2 = 0
P.f1 = A.f1 + A.f1 + B.f1 = 1
P.f2 = A.f2 + A.f2 + B.f2 = 4
如您所见,A.f1、B.f2、P.f1 和 P.f2 没有明确定义为方法,但由于继承和 meta-programming
考虑以下 Python 代码片段,我们在其中定义了 Portfolio
、Company
和 Deposit
class。 Portfolio
对象只是充当公司和存款的联合体。我们可以 运行 投资组合的指标,例如 Profit
。问题:
对于我在
Company
或Deposit
class 中包含的每个新指标,我需要在Portfolio
class;尽管他们的行为始终相同:对所有投资求和。有没有办法改进 logic/construction of classes? 如果我们需要添加 100 个其他指标怎么办...Deposit
class只有Profit
的功能,没有Loss
的功能(假定银行账户利息有保障) .有没有办法将 "undefined" 指标视为始终返回 0?或者是否有 cleaner/more 正确定义这些指标? 如果我们需要涵盖 100 种可能有或可能没有不同指标的不同投资类型怎么办...
class Company():
def __init__(self, ItemsSold, ItemPrice, Expenses, Fines):
self.ItemsSold = ItemsSold
self.ItemPrice = ItemPrice
self.Expenses = Expenses
self.Fines = Fines
def Profit(self):
return self.ItemsSold * self.ItemPrice
def Loss(self):
return self.Expenses + self.Fines
def ProfitAndLoss(self):
return self.Profit() - self.Loss()
class Portfolio():
def __init__(self, Investments):
self.Investments = Investments
def Profit(self):
return sum([inv.Profit() for inv in self.Investments])
def Loss(self):
return sum([inv.Loss() for inv in self.Investments])
def ProfitAndLoss(self):
return sum([inv.ProfitAndLoss() for inv in self.Investments])
class Deposit():
def __init__(self, Notional, InterestRate, TimeHorizon):
self.Notional = Notional
self.InterestRate = InterestRate
self.TimeHorizon = TimeHorizon
def Profit(self):
return self.Notional * self.InterestRate * self.TimeHorizon
myComp1 = Company(100,2,50,20)
myComp2 = Company(200,2,100,80)
myDepos = Deposit(100,0.02,3)
myPortf = Portfolio([myComp1,myComp2,myDepos])
print(myPortf.Profit()) # Works fine
print(myPortf.ProfitAndLoss()) # Throws an error
第二个问题很简单:您所要做的就是创建一个 Base
class,其中每个指标都定义为返回 0 的方法。然后派生所有 Invest
classes (Company
, Deposit
, etc) 来自 Base
class,因此所有未定义的指标将调用 [=12= 中的相应方法] class.
第一个问题有点难,因为它需要 meta-programming。你的Portfolio
class也可以从Base
class派生出来,然后在Base
class的方法字典中查找(Base.__dict__
) 检索所有指标名称。之后,对于所有这些指标,它会创建一个特定的 lambda 方法,该方法会为 Investments
列表中的每个项目调用此指标并对结果求和。这是一个框架代码:
class Base(object):
def f1(self):
return 0
def f2(self):
return 0
class InvestA(Base):
def f2(self):
return 2
class InvestB(Base):
def f1(self):
return 1
class Portfolio(Base):
def __init__(self, invest):
self.invest = invest
for name in [n for n in Base.__dict__ if n[:2] != '__']:
self.__dict__[name] = lambda name=name: self.sum(name)
def sum(self, name):
return sum([i.__class__.__dict__[name](i) for i in self.invest
if name in i.__class__.__dict__])
A = InvestA()
print("A.f1 = %s, A.f2 = %s" % (A.f1(), A.f2()))
B = InvestB()
print("B.f1 = %s, B.f2 = %s" % (B.f1(), B.f2()))
P = Portfolio([A,A,B])
print('P.f1 = A.f1 + A.f1 + B.f1 =', P.f1())
print('P.f2 = A.f2 + A.f2 + B.f2 =', P.f2())
产生以下输出:
A.f1 = 0, A.f2 = 2
B.f1 = 1, B.f2 = 0
P.f1 = A.f1 + A.f1 + B.f1 = 1
P.f2 = A.f2 + A.f2 + B.f2 = 4
如您所见,A.f1、B.f2、P.f1 和 P.f2 没有明确定义为方法,但由于继承和 meta-programming