Implementing __init__() in a superclass
We initialize an object by implementing the __init__()
method. When an object is created, Python first creates an empty object and then calls the __init__()
method for that new object. This method function generally creates the object's instance variables and performs any other one-time processing.
The following are some example definitions of a Card
class hierarchy. We'll define a Card
superclass and three subclasses that are variations of the basic theme of Card
. We have two instance variables that have been set directly from argument values and two variables that have been calculated by an initialization method:
class Card: def __init__( self, rank, suit ): self.suit= suit self.rank= rank self.hard, self.soft = self._points() class NumberCard( Card ): def _points( self ): return int(self.rank), int(self.rank) class AceCard( Card ): def _points( self ): return 1, 11 class FaceCard( Card ): def _points( self ): return 10, 10
In this example, we factored the __init__()
method into the superclass so that a common initialization in the superclass, Card
, applies to all the three subclasses NumberCard
, AceCard
, and FaceCard
.
This shows a common polymorphic design. Each subclass provides a unique implementation of the _points()
method. All the subclasses have identical signatures: they have the same methods and attributes. Objects of these three subclasses can be used interchangeably in an application.
If we simply use characters for suits, we will be able to create Card
instances as shown in the following code snippet:
cards = [ AceCard('A', '♠'), NumberCard('2','♠'), NumberCard('3','♠'), ]
We enumerated the class, rank, and suit for several cards in a list. In the long run, we need a much smarter factory function to build Card
instances; enumerating all 52 cards this way is tedious and error prone. Before we get to the factory functions, we take a look at a number of other issues.