Aiming for simplicity using the callable API

The idea behind a callable object is that we have an API that's focused on a single method.

Some objects have multiple relevant methods. A Blackjack Hand, for example, has to add cards and produce a total. A blackjack Player has to place bets, accept hands, and make play decisions (for example, hit, stand, split, insure, double down, and so on). These are more complex interfaces that are not suitable to be callables.

The betting strategy, however, is a candidate for being a callable.

The betting strategy can either be implemented as several methods (some setters and a getter method) or it can be a callable interface with a few public attributes.

The following is the straight betting strategy. It is always the same:

class BettingStrategy:
    def __init__( self ):
       self.win= 0
       self.loss= 0
    def __call__( self ):
        return 1
bet=  BettingStrategy()

The idea of this API is that a Player object will inform the betting strategy of win amounts and loss amounts. The Player object might have methods such as the following to inform the betting strategy about the outcome:

    def win( self, amount ):
        self.bet.win += 1
        self.stake += amount
    def loss( self, amount ):
         self.bet.loss += 1
         self.stake -= amount

These methods inform a betting strategy object (the self.bet object) whether the hand was a win or a loss. When it's time to place a bet, the Player will perform something like the following operation to get the current betting level:

    def initial_bet( self ):
        return self.bet()

This is a pleasantly short API. After all, the betting strategy doesn't do much other than encapsulate a few, relatively simple rules.

The shortness of this interface is one of the elegant features of a callable object. We don't have many method names, and we don't have a complex set of syntaxes for a simple thing.