Initializing static methods
When we have multiple ways to create an object, it's sometimes more clear to use static methods to create and return instances rather than complex __init__()
methods.
It's also possible to use class methods as alternate initializers, but there's little tangible advantage to receiving the class as an argument to the method. In the case of freezing or splitting a Hand
object, we might want to create two new static methods to freeze or split a Hand
object. Using static methods as surrogate constructors is a tiny syntax change in construction, but it has huge advantages when organizing the code.
The following is a version of Hand
with static methods that can be used to build new instances of Hand
from an existing Hand
instance:
class Hand5: def __init__( self, dealer_card, *cards ): self.dealer_card= dealer_card self.cards = list(cards) @staticmethod def freeze( other ): hand= Hand5( other.dealer_card, *other.cards ) return hand @staticmethod def split( other, card0, card1 ): hand0= Hand5( other.dealer_card, other.cards[0], card0 ) hand1= Hand5( other.dealer_card, other.cards[1], card1 ) return hand0, hand1 def __str__( self ): return ", ".join( map(str, self.cards) )
One method freezes or creates a memento version. The other method splits a Hand5
instance to create two new child instances of Hand5
.
This is considerably more readable and preserves the use of the parameter names to explain the interface.
The following code snippet shows how we can split a Hand5
instance with this version of the class:
d = Deck() h = Hand5( d.pop(), d.pop(), d.pop() ) s1, s2 = Hand5.split( h, d.pop(), d.pop() )
We created an initial h
instance of Hand5
, split it into two other hands, s1
and s2
, and dealt an additional Card
class into each. The split()
static method is much simpler than the equivalent functionality implemented via __init__()
. However, it doesn't follow the pattern of creating a fronzenset
object from an existing set
object.