Search code examples
pythonfunctionpygamecard

Python card game efficiency


I'm working on a card game in python. I already made a card Class and a deck Class. I'm using pygame so i made a function that turns string card suits to symbols to display them on top of the cards. My question is that is it more efficiency to write these functions in the class or outside of it and why. Thank you!

Inside:

class Card:
    def __init__(self, value, suit):
        self.value = value
        self.suit = suit

    def get_suit(self):
        if self.suit == "Clubs":
            return '♣'
        elif self.suit == "Hearts":
            return '♥'
        elif self.suit == "Diamonds":
            return '♦'
        elif self.suit == "Spades":
            return '♠'

    def get_value(self):
        if self.value >= 7 and self.value <= 10:
            return self.value
        elif self.value == 11:
            return "J"
        elif self.value == 12:
            return "Q"
        elif self.value == 13:
            return "K"
        elif self.value == 14:
            return "A"

or outside:

def get_suit(suit):
    if suit == "Clubs":
        return '♣'
    elif suit == "Hearts":
        return '♥'
    elif suit == "Diamonds":
        return '♦'
    elif suit == "Spades":
        return '♠'

def get_value(value):
    if value >= 7 and value <= 10:
        return value
    elif value == 11:
        return "J"
    elif value == 12:
        return "Q"
    elif value == 13:
        return "K"
    elif value == 14:
        return "A"      
                
            
class Card:
    def __init__(self, value, suit):
        self.value = value
        self.suit = suit

Solution

  • They should be methods - they are directly related to the card itself, and they both use attributes of the Card: as functions you would always have to pass in an attribute off an object anyway - so why not have them as methods.

    As a teaching point there are more efficient ways to write these - I hope you don't mind this extra information.

    instead of using if/else you can use dictionaries (each if tests the same attrribute against single value per if statement and each if statement returns a simple value - a classic case where dictionaries really work).

    Your methods would become :

        def get_suit(self):
            return {"Clubs":'♣',"Hearts":'♥',"Diamonds":'♦',"Spades":'♠'}[self.suit]
    
        def get_value(self):
            return {11:"J",12:"Q",13:"K",14:"A"}.get(self.value,self.value)
    

    Hopefully the get_suit method should be self explanatory assuming you know the basics of dictionaries.

    The get_value method uses a feature of dictionaries that not many begineers are familiar with, which is the get() method. The get method takes two arguments, the first is the key to look for (in this case the card value) and the default to return if the key doesn't exist in the dictionary (which is also the card value). So in this case if the value is 11 to 14 inclusive the get method returns J to A respectively, and if value is outside this 11 to 14 range you get the value.

    I hope you can see how this technique of using dictionaries is easily extensible, and usable in many different ways; where as the if/else chain explodes into multiple code lines very quickly.

    Good luck.