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()
2 Answers 2
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
3 Comments
[ Player(0) for _ in range(self.numPlayers) ]? This actually works perfectly, now everything works!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)]
playeris not aPlayerinstance; it is a string.Playerinstance withp1, so why I can't again use method ofPlayerwith samep1?Playerobjects anywhere; theplayerListobject is not updated.