5.4 可调用API和复杂性
我们一起看一下这个API是如何应对逻辑由简单变为复杂的。如下是对于输策略的加注逻辑(也称为鞅投注系统)。
class BettingMartingale( BettingStrategy ):
def init( self ):
self.win= 0
self.loss= 0
self.stage= 1
@property
def win(self): return self._win
@win.setter
def win(self, value):
self._win = value
self.stage= 1
@property
def loss(self): return self._loss
@loss.setter
def loss(self, value):
self._loss = value
self.stage *= 2
def __call( self ):
return self.stage
通过将loss方法中的stage乘2来完成加注逻辑。加注操作会一直进行,直到赢一局,补偿之前的损失;或者达到了下注的最大值;或者破产了。玩牌时通常添加下注最大值来阻止不断的加注。
每当赢一局,重置为第1次的下注数额。相应地,stage变量也会被重置为1。
为了维护接口的稳定。需要完成如bet.win += 1这样的代码逻辑时,可通过创建特性来根据输赢的变化维护状态值的改变。我们只关心setter特性,可为了更清晰地创建setter特性,需要定义getter特性。
可根据如下代码这样使用此类。
>>> bet= BettingMartingale()
>>> bet()
1
>>> bet.win += 1
>>> bet()
1
>>> bet.loss += 1
>>> bet()
2
API的逻辑仍然很简单:如果赢了,赢的数量累加并重置下注对象;如果输了,输的数量累加并翻倍下注。
特性的加入使得类的定义看起来很臃肿。我们只关心setter而非getter,因此可像如下代码使用setattr()()函数来简化类定义。
class BettingMartingale2( BettingStrategy ):
def init( self ):
self.win= 0
self.loss= 0
self.stage= 1
def setattr( self, name, value ):
if name == 'win':
self.stage = 1
elif name == 'loss':
self.stage *= 2
super().setattr( name, value )
def call( self ):
return self.stage
我们使用了setattr()函数来监控win和loss值的变化。另外,使用了super().setattr()函数设置了实例变量值,同时也更新了下注数额。
这个类定义更好一些。使用了可调用对象中的两个属性来作为API。
