estranged
estranged

Reputation: 432

Passing class instance in the method argument

I am learning OOP, have hard time grasping how to different classes interact with each other. I read so many examples but majority of them show how single class works, and that's clear, I want to see how different classes to interact among themselves. If someone has a good example how different classes interact it would be great.

Here I create Deck instance newDeck and then Player instance p1. Then I do this: newCard.append(player.generateCard(newDeck)) where player is p1, so I call Player method generateCard() and pass newDeck instance of class Deck. Is this allowed?

Here I get error:

   File "poker.py", line 67, in startGame
    newCard.append(player.generateCard(newDeck))
AttributeError: 'str' object has no attribute 'generateCard'`

My code:

import random, string, sys

class Deck:
    def __init__(self):
        self.suits = ['s', 'h', 'd', 'c']
        self.ranks = ['2', '3', '4', '5', '6' ,'7', '8', '9', '10', 'J', 'Q', 'K', 'A']
        self.deck = [i+j for i in self.ranks for j in self.suits]
        random.shuffle(self.deck)

    def selectCards(self):
        self.selectedCard = self.deck.pop()
        return self.selectedCard

class Player:
    def __init__(self, amount):
        self.amount = amount
        self.card = []

    def generateCard(self, whichDeck):
        self.whichDeck = whichDeck
        holeCards = 2
        for i in range(0, holeCards):
            selCard = self.whichDeck.selectCards()
            if len(selCard) == 2:
                self.cardRank = list(selCard[0])
            else:
                self.cardRank = list('10') 
            self.cardSuit = list(selCard[-1])
            self.generatedCard = list(self.cardRank + self.cardSuit)
            self.card.append(self.generatedCard)
        return self.card 

class Game:
    def __init__(self, numPlayers, startingStack):
        self.startingStack = startingStack
        self.numPlayers = numPlayers

    def startGame(self):
        newDeck = Deck()
        playerList = ['p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', 'p8']
        currentPlayer = 0
        for player in playerList:
            player = Player(self.startingStack)
            currentPlayer += 1 
            if currentPlayer == self.numPlayers:
                break
        totalPlayers = currentPlayer
        # -------------------------- GAME STARTS ---------------------------
        newCard = []
        currentPlayer = 0
        for player in playerList:                
            newCard.append(player.generateCard(newDeck)) # ERROR IS HERE               
            if currentPlayer == self.numPlayers:
                break

def main():
    numberOfPlayers = 1
    playerStack = 100
    newGame = Game(numberOfPlayers, playerStack)    
    newGame.startGame()
if __name__ == '__main__':
    main()

Upvotes: 0

Views: 381

Answers (2)

Martijn Pieters
Martijn Pieters

Reputation: 1121494

Your playerList object is still a list of strings. Your loop:

for player in playerList:
    player = Player(self.startingStack)
    currentPlayer += 1 
    if currentPlayer == self.numPlayers:
        break

re-binds player to a Player() instance, but this doesn't change the playerList object. In fact, by the time you get to the next iteration, the Player() instance is discarded again as nothing else references it.

The for player in playerList binds player to each string in the list in turn, but the reference does not work the other direction, player is just another Python name, another reference to the same object contained in playerList. Assigning a different object to it will not also alter the list from which the strings were taken.

You probably wanted to build a new list here:

def startGame(self):
    newDeck = Deck()
    playerList = ['p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', 'p8']
    players = []
    for player in playerList[:self.numPlayers]:
        player = Player(self.startingStack)
        players.append(player)
    totalPlayers = self.numPlayers
    # -------------------------- GAME STARTS ---------------------------
    newCard = []
    for player in players:           
        newCard.append(player.generateCard(newDeck))

However, you are entirely ignoring the strings in playerList here; may as well just build the list without consulting those:

def startGame(self):
    newDeck = Deck()
    players = [Player(self.startingStack) for _ in range(self.numPlayers)]
    newCard = [player.generateCard(newDeck) for player in players]

but you don't need players then as a separate list either:

def startGame(self):
    newDeck = Deck()
    newCard = [Player(self.startingStack).generateCard(newDeck)
               for _ in range(self.numPlayers)]

Upvotes: 0

lejlot
lejlot

Reputation: 66785

You do not have any Player instances, you create list of strings:

playerList = ['p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', 'p8']

then in the loop you just do

for player in playerList:
        player = Player(self.startingStack)
        currentPlayer += 1 
        if currentPlayer == self.numPlayers:
            break

and this local variable player is lost, it is not magically appended to your playerList

Simply do something like

playerList = [ Player(self.startingStack) for _ in range(self.numPlayers) ]

instead of your loop

Upvotes: 1

Related Questions