25. Inheritance and Related OOP* Ideas

25. Inheritance and Related OOP* Ideas

25. Inheritance and Related OOP* Ideas Topics: The classes Card, Deck and Hand Subclasses Inheritance Method Overriding *OOP = Object Oriented Programming Will Cover These Topics With a Single Example It will involve operations with playing cards. Closely follows Chapter 18 in Think Python We Are Going to Define Three Classes class Card: “““ Represents a single playing card.””” class Deck: “““ Represents a deck of cards””” class Hand: “““ Represents a hand of cards””” Decks and Hands Things to do with a deck of cards: 1. Shuffle 2. Sort* 3. Add a card 4. Remove a card Things to do with a hand of cards: 1. Compare 2. Sort* 3. Add a card 4. Remove a card *Maybe sort in different ways Representing a Card A card has a suit and a rank. There are 4 possible suits. There are 13 possible ranks. Anticipate a class with two attributes Representing a Card A card has a suit and a rank. There are 4 possible suits. There are 13 possible ranks ['Clubs','Diamonds','Hearts','Spades'] ['Ace','Two','Three', 'Four','Five','Six', 'Seven','Eight','Nine’,'Ten', 'Jack', 'Queen','King'] The Class Card class Card: suit_names = rank_names = def __init__(self,suit,rank): def __str__(self): def __cmp__(self,other): The Class Card class Card: suit_names = Class Variable rank_names = Class Variable def __init__(self,suit,rank): Constructor def __str__(self): For pretty printing def __cmp__(self,other): For comparing one card to another Class Variables suit_names = ['Clubs', 'Diamonds', 'Hearts','Spades’ ] rank_names = [None, 'Ace', 'Two', 'Three', 'Four', 'Five','Six', 'Seven', 'Eight','Nine’,'Ten', 'Jack', 'Queen','King'] Class Variables suit_names = ['Clubs', 'Diamonds', 'Hearts','Spades’ ] rank_names = [None, 'Ace', 'Two', 'Three', 'Four', 'Five','Six', 'Seven', 'Eight','Nine’,'Ten', 'Jack', 'Queen','King'] Putting None in the 0th entry makes for more intuitive subscripting: rank_names[7] is ‘Seven’ Suits are “Indexed” suit_names = ['Clubs', 'Diamonds', 'Hearts','Spades’ ] 0 Clubs 1 Diamonds 2 Hearts 3 Spades An ordering: Clubs < Diamonds < Hearts < Spades Class Variables suit_names = ['Clubs', 'Diamonds', 'Hearts','Spades’ ] rank_names = [None, 'Ace', 'Two', 'Three', 'Four', 'Five','Six', 'Seven', 'Eight','Nine’,'Ten', 'Jack', 'Queen','King'] The Class Card class Card(object): suit_names = rank_names = def __init__(self,suit,rank): Constructor def __str__(self): def __cmp__(self,other): Let’s look at the constructor… The Constructor: Basic Idea def __init__(self,suit,rank): """ suit and rank are ints """ self.suit = suit self.rank = rank c = Card(2,8) Says: Create a card object that represents the eight-of-hearts The Constructor With a Convenient no-Argument Option We’d like c = Card() to generate a random Card. def __init__(self,suit=None,rank=None): if suit==None and rank==None: self.suit = randi(0,3) # random suit self.rank = randi(1,13) # random rank else: self.suit = suit self.rank = rank Using the Optional Argument Idea The Class Card class Card(object): suit_names = rank_names = def __init__(self,suit,rank): def __str__(self): For pretty printing def __cmp__(self,other): Let’s look at the __str__ method… def __str__(self) A special method that “pretty prints” a card when we use print >>> c = Card(2,13) >>> print c King of Hearts def __str__(self) suit_names = ['Clubs', 'Diamonds', 'Hearts','Spades’ ] def __str__(self): i = self.suit # suit index theSuit = self.suit_names[i] j = self.rank # rank index theRank = self.rank_names[j] return theRank + ‘ ‘ + theSuit Shows how to access class variables The Class Card class Card(object): suit_names = rank_names = def __init__(self,suit,rank): def __str__(self): def __cmp__(self,other): For comparing one card to another Let’s look at the __cmp__ method… Comparing Cards What we’d like to do: >>> C1 = Card(2,13) # King of Hearts >>> C2 = Card(0,5) # Five of Clubs >>> C1 > C2 True The __cmp__ method makes this possible Comparing Cards What we’d like to do if L is a list of references to Card objects: L.sort() Sorting requires comparisons for c in L: between the things that are being sorted print c The __cmp__ method makes this possible How Do We Compare 2 Cards? First compare their suits: Spades > Hearts > Diamonds > Clubs If there is a tie, then compare their ranks: K > Q > J > 10 > … > 2 > Ace How It Works def __cmp__(self,other): if self.suit > other.suit: return 1 if self.suit < other.suit: return -1 if self.rank > other.rank: return 1 if self.rank < other.rank: return -1 return 0 Returning +1 means that the Card self is greater than the Card other. How It Works def __cmp__(self,other): if self.suit > other.suit: return 1 if self.suit < other.suit: return -1 if self.rank > other.rank: return 1 if self.rank < other.rank: return -1 return 0 Returning -1 means that the Card self is less than the Card other. How It Works def __cmp__(self,other): if self.suit > other.suit: return 1 if self.suit < other.suit: return -1 if self.rank > other.rank: return 1 if self.rank < other.rank: return -1 return 0 Returning 0 means that the Card self is the same as the Card other. Example for k in range(7): YourCard = Card() Two random cards MyCard = Card() if YourCard > MyCard: Yours is “higher” Winner = 'You' elif MyCard > YourCard: Mine is “higher” Winner = 'Me' else: If we get here, the two Winner = 'Tie‘ cards are the same. print YourCard, MyCard, Winner Sample Output Your Card My Card Winner ---------------------------------------------------- Six of Hearts Six of Spades Me Eight of Spades Queen of Hearts You Five of Diamonds Queen of Clubs You Queen of Clubs Eight of Diamonds Me Two of Clubs Five of Spades Me Six of Clubs Four of Spades Me Nine of Clubs Seven of Spades Me This Completes the Discussion of the Class Card class Card(object): suit_names = rank_names = def __init__(self,suit,rank): def __str__(self): def __cmp__(self,other): Next Up : The Class Deck class Deck(object): def __init__(self,suit,rank): Constructor def __str__(self): Pretty Print def pop_card(self): Remove a card from the deck def add_card(self,card): Add a card to the deck def shuffle(self): Shuffle the Deck def sort(self): Sort the Deck The Attributes DeckOfCards: list of Card objects n: int n is the number of cards in the deck. The "top" of the deck is self.DeckOfCards[0] The "bottom" of the deck is self.DeckOfCards[self.n] The Constructor It will build a length-52 list of cards: def __init__(self): self.n = 52 self.DeckOfCards = [] for suit in range(4): for rank in range(1,14): card = Card(suit,rank) self.DeckOfCards.append(card) The Constructor def __init__(self): self.n = 52 self.DeckOfCards = [] for suit in range(4): for rank in range(1,14): card = Card(suit,rank) self.DeckOfCards.append(card) Nested loops are used to cover all possible suits and ranks. The Constructor def __init__(self): self.n = 52 self.DeckOfCards = [] for suit in range(4): for rank in range(1,14): card = Card(suit,rank) self.DeckOfCards.append(card) The list is built via repeated appending The Constructor def __init__(self): self.n = 52 self.DeckOfCards = [] for suit in range(4): for rank in range(1,14): card = Card(suit,rank) self.DeckOfCards.append(card) Reminder: one constructor can call another constructor. Create and Print a Deck Ace of Clubs D = Deck() Two of Clubs Three of Clubs print D Four of Clubs Five of Clubs Six of Clubs Seven of Clubs Eight of Clubs The __str__ method Nine of Clubs is invoked and produces Ten of Clubs Jack of Clubs 52 lines of output ----------------> Queen of Clubs King of Clubs Ace of Diamonds Two of Diamonds etc Randomly Shuffle a Card Deck def shuffleDeck(self): shuffle(self.DeckOfCards) Makes use of the list method shuffle. The list function shuffle >>> a = [1,2,3,4,5,6,7,8,9,10] >>> shuffle(a) >>> a [10, 1, 3, 9, 2, 5, 7, 4, 8, 6] >>> shuffle(a) >>> a [4, 9, 1, 3, 7, 10, 5, 6, 8, 2] This function can be applied to any list. A random permutation. NOT THE PERFECT SHUFFLE Create, Shuffle, and Print a Deck Jack of Spades Four of Hearts Seven of Diamonds Three of Spades D = Deck() Eight of Diamonds Seven of Clubs D.shuffle() Ace of Hearts Six of Spades print D Ace of Diamonds Five of Diamonds Eight of Clubs Eight of Hearts Queen of Diamonds Six of Diamonds Six of Hearts etc Remove a Card def pop_card(self,Where): return self.cards.pop() Recall how to pop an entry in a list: >>> x = [10,20,30,40] >>> x.pop(2) 30 >>> x [10, 20, 40] Remove a Card def pop_card(self,Where): if Where=='Top': c = self.DeckOfCards.pop(0) elif Where=='Bot': c = self.DeckOfCards.pop() elif Where==None: k = randi(0,self.n-1) c = self.DeckOfCards.pop(k) self.n -= 1 return c Three alternatives. The selected card can come off the top or bottom of the deck or it can be selected randomly. Add a Card to a Deck def add_card(self,card): self.DeckOfCards.append(card) self.DeckOfCcards is a list of cards Sort a Deck def sort(self): self.DeckOfCards.sort() This is possible because we defined a __cmp__ method in the Card class. An Example D = Deck() D.shuffle() for k in range(5): c = D.pop_card('Top') print c D.add_card(c) Create and shuffle a deck. Then repeatedly select a card off the top of the Deck, display it, and put it back in the deck at the bottom. This Completes the Discussion of the Deck Class class Deck(object): def __init__(self,suit,rank): def __str__(self): def pop_card(self): def add_card(self,card): def shuffle(self): def sort(self): Next Up: The Hand Class class Hand(Deck): def __init__(self,suit,rank): def __str__(self): def sort(self): The Hand Class class Hand(Deck): Usually we would write Hand(object) def __init__(self,suit,rank): def __str__(self): def sort(self): The Hand Class inherits all the methods from the Deck class.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    69 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us