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 to set the state of the new object. This method 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 using an initialization method:

from typing import Tuple

class
Card:

def __init__(self, rank: str, suit: str) -> None:
self.suit = suit
self.rank = rank
self.hard, self.soft = self._points()

def _points(self) -> Tuple[int, int]:
return int(self.rank), int(self.rank)

class AceCard(Card):

def _points(self) -> Tuple[int, int]:
return 1, 11

class FaceCard(Card):

def _points(self) -> Tuple[int, int]:
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 two subclasses, AceCard and FaceCard.

This example provides type hints for parameters of the __init__() method. Both the rank and suit parameters are expected to have values of the str type. The result of the __init__() method is always None, since it never returns a value. These hints can be checked by the mypy tool to ensure that the class is used properly.

This shows a common polymorphic design. Each subclass provides a unique implementation of the _points() method. The various _points() methods all return a two-tuple with the different ways to evaluate a card. 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.

The leading _ in the name is a suggestion to someone reading the class that the _points() method is an implementation detail, subject to change in a future implementation. This can help to reveal which methods are part of a public interface and which are details that aren't intended for general use by other classes.

If we simply use characters for suits, we will be able to create the Card instances, as shown in the following code snippet:

cards = [AceCard('A', '♠'), Card('2','♠'), FaceCard('J','♠'),]

We enumerated the class, rank, and suit for several cards in a list. In the long run, we'll 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 factory functions, we will take a look at a number of other issues.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset