Mastering Objectoriented Python
上QQ阅读APP看书,第一时间看更新

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.