Python Forum
Organizing list of objects by attribute
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Organizing list of objects by attribute
#1
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] 
Reply
#2
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)
Reply
#3
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))
Reply
#4
(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
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Organizing several similar classes with overlapping variables 6hearts 7 1,331 May-07-2023, 02:00 PM
Last Post: 6hearts
  Creating list of lists, with objects from lists sgrinderud 7 1,564 Oct-01-2022, 07:15 PM
Last Post: Skaperen
Question Keyword to build list from list of objects? pfdjhfuys 3 1,500 Aug-06-2022, 11:39 PM
Last Post: Pedroski55
  AttributeError: 'list' object has no attribute 'upper' Anldra12 4 4,721 Apr-27-2022, 09:27 AM
Last Post: Anldra12
  How to store the resulting Doc objects into a list named A xinyulon 1 1,855 Mar-08-2022, 11:49 PM
Last Post: bowlofred
  AttributeError: 'list' object has no attribute 'values' ilknurg 4 14,781 Jan-19-2022, 08:33 AM
Last Post: menator01
  Grouping and sum of a list of objects Otbredbaron 1 3,132 Oct-23-2021, 01:42 PM
Last Post: Gribouillis
  Passing List of Objects in Command Line Python usman 7 3,091 Sep-27-2020, 03:45 PM
Last Post: ndc85430
  How to create and define in one line a 2D list of class objects in Python T2ioTD 1 1,989 Aug-14-2020, 12:37 PM
Last Post: Yoriz
  How do I get attribute XPATHs list ? MDRI 3 2,810 Jun-24-2020, 07:28 AM
Last Post: snippsat

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020