![]() |
Organizing list of objects by attribute - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: Organizing list of objects by attribute (/thread-24835.html) |
Organizing list of objects by attribute - scarney1988 - Mar-06-2020 Hey guys/gals, I have been working on my first python project of modelling a deck of standard playing cards. I am hoping to program a basic card game and then begin making a GUI for it. I am stuck on getting the players hand organized. The card class has two attributes: value, suit. I would like to organize by 'value' so that I can come back check for pairs, 3 of a kind, etc... Also, I just started reviewing PEP-8 recently. So I will be reorganizing things after its all functional as a learning exercise. What do you guys/gals recommend from Card import Card class Deck: def __init__(self): self.deck_of_cards=[] def initialize_deck(self): suits = ["Hearts", "Clubs", "Spades", "Diamonds"] values = ["Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"] for suit in suits: for value in values: temp_card = Card() #create a temporary card for each iteration temp_card.setvalue(value) #set value and suit of temporary card prior to storage temp_card.setsuit(suit) self.deck_of_cards.append(temp_card) #store card in the Deck object def shuffle_deck(self): import random #Import "random" module to gain access to "random.shuffle()" random.shuffle(self.deck_of_cards) def draw_card(self): temp_card = self.deck_of_cards.pop() return(temp_card) def load_card(self, temp_card): self.deck_of_cards.append(temp_card) class Card: def __init__(self): self.value = "UNASSIGNED VALUE" self.suit = "UNASSIGNED SUIT" #def __init__(self, newvalue, newsuit): #self.value = newvalue #self.suit = newsuit def getvalue(self): return(self.value) def getsuit(self): return(self.suit) def setvalue(self, new_value): self.value=new_value def setsuit(self, new_suit): self.suit=new_suit def identify_card(self): print(self.getvalue(), "of", self.getsuit()) from Deck import Deck from Card import Card class Hand: def __init__(self): self.cards_in_hand = [] def look_hand(self): for card in self.cards_in_hand: card.identify_card() def draw_card(self, deck): self.cards_in_hand.append(deck.draw_card()) #def give_card(self): #FUNCTION WILL REMOVE A SPECIFIC CARD FROM HAND.CARDS_IN_HAND[]. #FUNCTION WILL RECIEVE A NUMBER WHICH CORRELATES TO THE INDEX LOCATION OF THE #CARD TO BE RETURNED BY THE FUNCTION #def sort_hand(self): #FUNCTION WILL ORDER THE HAND BY VALUE OF THE CARDS. #def check_hand(self): #FUNCTION WILL RETURN AN INTEGER WHICH CORRESPONDS TO HIGHEST CHANCE TO WIN #AND AN INTEGER WHICH CORRESPONDS TO THE HIGH CARD OF THE HAND, # HIGH CARD = 0 # PAIR = 1 # TWO PAIR = 2 # 3 OF A KIND = 3 # STRAIGHT = 4 # FLUSH = 5 # FULL HOUSE = 6 # 4 OF A KIND = 7 # STR8T FLUSH = 8 # ROYAL FLUSH = 9 # 4 OF A KIND = 3 # HIGH CARD: 2 = [0], 3 = [1] ... ACE = [13] RE: Organizing list of objects by attribute - stullis - Mar-06-2020 To sort by an attribute, you can use the sorted() built-in function. As for the code, I have a couple recommendations. You already have a commented out implementation of a better Card so I would get rid of the first one and the setter methods. You'll see why in a moment. Also, instead of Card.identify_card(), make use of the __str__() and __repr__() dunder methods (this is more advanced, but the implementation is easy and you can learn something new!). These methods work with the print() function to provide a custom output for each instance. class Card: def __init__(self, suit, value): self.value = value self.suit = suit def getvalue(self): return(self.value) def getsuit(self): return(self.suit) def __str__(self): return self.getvalue() + " of " + self.getsuit() def __repr__(self): return self.__str__()With those changes, we can make an improvement to Deck.initialize_deck(). First, give it the same treatment with Deck.__init__() to pass in the suits and values - this makes the Deck more versatile. Then, use a list comprehension (again, more advanced) to make the cards. List comprehensions are faster than loops and more pythonic. Then, add method calls to Deck.initialize_deck() and Deck.shuffle_deck() to Deck.__init__() so it's ready for dealing as soon as it's initialized. import random from Card import Card class Deck: def __init__(self, suits, values): self.deck_of_cards=[] self.suits = suits self.values = values self.initialize_deck() self.shuffle_deck() def initialize_deck(self): self.deck_of_cards = [Card(s, v) for s in suits for v in values] def shuffle_deck(self): random.shuffle(self.deck_of_cards) def draw_card(self): return self.deck_of_cards.pop() def load_card(self, temp_card): self.deck_of_cards.append(temp_card) RE: Organizing list of objects by attribute - scarney1988 - Mar-07-2020 Thank you. That was a great response. Very very helpful. I had initially went with the set methods because I wanted to eventually add in a Joker card which the user could input value and suit. I guess I could just use something like the following to achieve that: def assign_joker(joker_card): # FUNCTION CALLED TO TAKE USER INPUT FOR CARD VALUE / SUIT (OMITTED), THEN RETURN THE CARD # PROPERLY ASSIGNED AS FOLLOWS return (joker_card = Card(chosen_value, chosen_suit)) RE: Organizing list of objects by attribute - scarney1988 - Mar-11-2020 (Mar-06-2020, 03:20 PM)stullis Wrote: To sort by an attribute, you can use the sorted() built-in function. Thank you. I was able to code the following to accomplish my task: self.cards_in_hand = sorted(self.cards_in_hand, key=lambda x: x.value, reverse=True)Thanks again, Sean |