Search code examples
pythonlistobjectooplist-comprehension

Struggling to print objects in Python using list comprehension


I am learning Python for the first time and am trying to build a full fledged object oriented program, based on a childhood nursery rhyme/game about counting fists (Bubblegum Bubblegum in a Dish...)

I have a class/Player object, which has fists as an attribute. There is a fist class. My issue is, I cannot figure out how to get the 'fists' of each player object to print because the fists are objects. I tried using a list comprhension and also str and repr overrides with the list comprehension, and no dice. Below is the code associated with my most recent attempt... I would appreciate if someone could show/explain to me where I am going wrong. Thanks for your time!

The result of my most recent attempt is this: [<main.Fist object at 0x7f3d73f7e280>, <main.Fist object at 0x7f3d73f7e3a0>] [<main.Fist object at 0x7f3d73f7e490>, <main.Fist object at 0x7f3d73f7e4f0>]

  class Fist:
   
   Labels = ['Left', 'Right']
   
    # Constructor for fists
   def __init__(self, label):
        self.label = label  # this is just for testing purposes
        
   
   # Overriding Python Built in Functions so Our Objects Print Cleanly
   
   def __str__(self):
       return f"{self.label}"


class Player():
    
    # 1 - Player creates player objects for EACH player specified
    # by the user. 
    
    def __init__(self, name):
        self.name = name
        self.fists = [] # like deck, this holds fists
        
    
     # 2 - All users start out with TWO fists, so let's create those fists below:
    
        for Label in Fist.Labels:
           self.fists.append(Fist(Label))
           # print(self.fists.Fist.label)
            
        
    # 3 - The amount of fists remaining PER USER is kept track of
    # - When any player reaches a fist count of zero, they are
    # knocked out immedately
    
    def check_fist_count(self):
            if self.fists == 0:
             print(f'{self.name} fist count is now zero. They now are out of the game!')
             
           
             
     # Overriding Python Built in Functions so Our Objects Print Cleanly
    def __str__(self):
        return self.name + ': ' + ' '.join([str(fist) for fist in self.fist])
        
    
if __name__ == '__main__':
    
    # Ask the user for the number of players, create one player object per player
    # If players entered are 0 or 1 terminate
    
    numberOfPlayers = int(input("Bubblegum Nursery Rhyme Game: How many players will be playing this game?"))
    
    if numberOfPlayers <= 1 :
        print('Sorry, you can only play this game if you have a minimum of 2 players.')
    
    # Create the players based on the numberOfPlayers
    game_players = []
    for i in range(0,numberOfPlayers):
        game_players.append(Player(f'Player {i}'))
        

# Print tests on fists
 
for game_player in game_players:
  
 print(game_player.fists)
 
 #print([str(item) for item in game_player.fists])

Solution

  • You were actually pretty close! You just need to add a __repr__ special method to your classes, as the string formatting calls that method. Here is a way to fix the code:

    class Fist:
       
       Labels = ['Left', 'Right']
       
        # Constructor for fists
       def __init__(self, label):
            self.label = label  # this is just for testing purposes
            
       
       # Overriding Python Built in Functions so Our Objects Print Cleanly
       
       def __str__(self):
           return f"{self.label}"
       
       def __repr__(self):
           return f"Fist({self.label})"
    
    
    class Player():
        
        # 1 - Player creates player objects for EACH player specified
        # by the user. 
        
        def __init__(self, name):
            self.name = name
            self.fists = [] # like deck, this holds fists
            
        
         # 2 - All users start out with TWO fists, so let's create those fists below:
        
            for Label in Fist.Labels:
               self.fists.append(Fist(Label))
               # print(self.fists.Fist.label)
                
            
        # 3 - The amount of fists remaining PER USER is kept track of
        # - When any player reaches a fist count of zero, they are
        # knocked out immedately
        
        def check_fist_count(self):
                if self.fists == 0:
                 print(f'{self.name} fist count is now zero. They now are out of the game!')
                 
               
                 
        # Overriding Python Built in Functions so Our Objects Print Cleanly
        def __str__(self):
            return self.name + ': ' + ' '.join([str(fist) for fist in self.fists])
        
        def __repr__(self):
            return f"Player({self.name}, {self.fists})"
        
    if __name__ == '__main__':
        
        # Ask the user for the number of players, create one player object per player
        # If players entered are 0 or 1 terminate
        
        numberOfPlayers = int(input("Bubblegum Nursery Rhyme Game: How many players will be playing this game?"))
        
        if numberOfPlayers <= 1 :
            print('Sorry, you can only play this game if you have a minimum of 2 players.')
        
        # Create the players based on the numberOfPlayers
        game_players = []
        for i in range(0,numberOfPlayers):
            game_players.append(Player(f'Player {i}'))
            
    
    # Print tests on fists
     
    for game_player in game_players:
        print(game_player)
     
     #print([str(item) for item in game_player.fists])