# CS1/examples/Coins.py David MacQuigg 8-Sept-07 '''This module has all the different classes of coins.''' import random # Function random.random() returns a random float, # uniform in range [0.0, 1.0) __all__ = ['BiasedCoin', 'FairCoin'] # all items in the public API # everything else is "private" #** class _PrivateCoin: '''A leading _underscore is another way to make a class private.''' def _privateMethod(self): print ("Didn't you see all those _underscores?\n" "Keep out of my private parts, you peeper!" ) class TemplateCoin: '''Use this as a template for other classes. All coins in this module should have the same "interface", i.e. the same public methods and arguments and the same return types. Just copy this template class, and replace its implementation details. Use the testInterfaces function below to verify.''' def __init__(self, bias=0.6): # Initialize a new coin, default bias 0.6 if not 0 <= bias <= 1: raise ValueError, "bias must be in range 0.0 to 1.0" self.bias = bias # Instance variable set to passed-in arg def toss(self): '''returns True if result is heads, False otherwise''' if random.random() < self.bias: return True else: return False class BiasedCoin: '''A biased coin is more likely to return one result over another.''' def __init__(self, bias=0.6): if not 0 <= bias <= 1: raise ValueError, "bias must be in range 0.0 to 1.0" self.bias = bias def toss(self): '''returns True if result is heads, False otherwise''' if random.random() < self.bias: return True else: return False class FairCoin: '''Uses paired tosses of a biased coin to generate an unbiased result (von Neumann's method)''' def __init__(self, bias=0.6): if not 0.1 <= bias <= 0.9: # will take too many tosses raise ValueError, "bias must be in range 0.1 to 0.9" self.coin = BiasedCoin(bias=bias) def toss(self): '''Due to the symmentry of the experiment, there is equal probability that the returned result will be True or False.''' while True: # loop forever r1 = self.coin.toss() r2 = self.coin.toss() if r1 != r2: return r1 #** if __name__ == '__main__': '''Test the interface of each class to verify that it conforms.''' def testInterfaces(classList): '''To check that a new class does conform to the expected interface, add it to the classList here. It it doesn't throw an exception, your interface is OK.''' for Coin in (classList): coin = Coin(bias=0.3) result = coin.toss() assert result in (True, False, None) print '%-22s %-s' % (Coin, result ) classList = (TemplateCoin, BiasedCoin, FairCoin) testInterfaces(classList)