This chapter builds on the previous two chapters, creating a more complete composite object from the Outcome and Bin classes we have already defined. We’ll introduce some basic subclass constructor techniques, also.
The wheel has two responsibilities: it is a container for the Bins and it picks one Bin at random. We’ll also have to look at how to initialize the various Bins that comprise a standard Roulette wheel.
In this case, the choice of the winning Bin will be selected by a random numeric index. We need some kind of sequential collection.
This makes an immutable tuple very appealing. This is a subclass of collections.Sequence and has the features we’re looking for.
One consequence of using a sequential collection is that we have to choose an index for the various Bins. Each Bin contains a variety of individual Outcomes. However, each single number Outcome will be unique to each Bin.
The index values of 1 to 36 become the index to their respective Bins. The Bin at index 1 is the only bin which contains Outcome( "1", 35 ).
We have a small problem, however, with 0 and 00: we need two separate indexes. While 0 is a valid index, what do we do with 00?
Enumerate some possible solutions before reading on.
Python programmers can use the random module. This module offers a Random.choice() function which picks a random value from a sequence. This is ideal for returning a randomly selected Bin from our list of Bins.
Testability. Note that testing a class using random numbers isn’t really the best policy. To do testing properly, we’ll need to create a non-random random number generator that we can use in place of the published library random number generator.
To create a non-random random-number generator, we can so something like the following.
Constructing the entire collection of Bins would be a tedious undertaking. We’ll apply a common OO principle of deferred binding and work on that algorithm later, after we have the basic design for the Wheel finished.
Contains the individual Bin instances.
This is a tuple of 38 elements. This can be built with tuple( Bin() for i in range(38) )
The random number generator to use to select a Bin from the bins collection.
This is not always simply random.Random(). For testing, we need to inject a non-random random number generator in place of the system random number generator.
|Parameter:||rng (random.Random) – A “random” number generator. For testing, this may be a non-random number generator.|
Creates a new wheel with 38 empty Bins. It will also create a new random number generator instance.
At the present time, this does not do the full initialization of the Bins. We’ll rework this in a future exercise.
Generates a random number between 0 and 37, and returns the randomly selected Bin.
The Random.choice() function of the random module will select one of the available Bin s from the bins list.
|Returns:||A Bin selected at random from the wheel.|
Returns the given Bin from the internal collection.
|Parameter:||bin (int) – bin number, in the range zero to 37 inclusive.|
|Returns:||The requested Bin.|
We need a controlled kind of random number generation for testing purposes.
We’ll define a class NonRandom that extends random.Random, but provides a more testable sequence of values. One approach is to simply return a given integer value.
Saves this value as the next value to return.
|Parameter:||value (long) – the value to return next.|
Use the given seed value as an index and return the requested item from the sequence.
|Parameter:||sequence – the sequence of values from which a random value is selected.|
There are three deliverables for this exercise. The new class and the unit test will have Javadoc comments or Python docstrings.