python: атрибут экземпляра, действующий как атрибут класса
[Я новичок в изучении Python, это также мой первый пост о переполнении стека. Я искал решение широко, здесь и в других местах, но безуспешно. Извинения за большой кусок кода, который я должен вставить, чтобы продемонстрировать свою проблему, я оставил все, что не имеет отношения к делу.]
Итак, я делаю Udemy 'Complete Python Bootcamp' и застреваю в Milestone Project 2 (разработка игры в блэкджек). Насколько я знаю, проблема в том, что "hand", атрибут класса "Player", должен быть атрибутом экземпляра, но действует как атрибут класса. Таким образом, когда создается игра с X игроками, вместо того, чтобы каждый игрок заканчивал тем, что держал в руках две выпущенные им карты, все игроки заканчивали тем, что держали все карты (2*X), выпущенные любому игроку.
Код и выводы ниже. Я использую Python 3.6.0.
Любая помощь высоко ценится!
import random
from IPython.display import clear_output
def reset_usedcards():
global usedcards
usedcards = []
reset_usedcards()
class Card:
def __init__(self, color, number):
self.color = color
self.number = number
self.value = number
self.all = (self.color, (self.number[0],self.number[1]))
def __str__(self):
return '%s of %s' %(self.number[0], self.color)
dummycard = Card(color='',number=(0,0))
emptyhand = [dummycard,dummycard,dummycard]
def dealacard(usedcards): #returns a randomly selected card still available from the stack
colors = ['Hearts','Cross','Diamonds','Spades']
numbers = [(2,2), (3,3), (4,4), (5,5), (6,6), (7,7), (8,8), (9,9), (10,10), ('J',10), ('Q',10), ('K',10), ('A',11)]
while len(usedcards) < 52:
dealtcard = Card(random.choice(colors), random.choice(numbers))
if dealtcard.all in usedcards:
pass
else:
usedcards.append(dealtcard.all)
return(usedcards[-1])
break
else:
print('STACK IS GONE')
class Player: #when a new instance of the class Player is created, it automatically gets dealt two cards
def __init__(self,name,hand=[],balance=0):
self.name = name
self.hand = hand
self.balance = balance
for i in range(0,2):
self.hand.append(dealacard(usedcards))
def printhand(self):
print('Current hand:')
print(self.hand[0])
print(self.hand[1])
if self.hand[2].all[0] != '':
print(self.hand[2])
else:
pass
emptyplayer = Player('',emptyhand,0)
class Game: #instance of game is created with the numbers of players provided via argument.
#I've left out the parts of the code not relevant for this post.
def __init__(self,np,dealer='dealer',players=[emptyplayer]*6,bets=0):
self.np = np
self.dealer = dealer
self.players = players
self.bets = bets
reset_usedcards()
for n in range (0,np):
global tempplname
tempplname = 'player'+str(n+1)
self.players[n] = Player(name=tempplname)
print(f'\nGame created with {np} players')
def __str__(self):
print('Players in game:')
for i in range (0,self.np):
print(str(self.players[i]))
return ''
Результат:
game = Game(4)
Игра создана с 4 игроками
str(game.players[0].hand)
"[(" Алмазы ", (6, 6)), (" Сердца ", (5, 5)), (" Пики ", (" А ", 11)), (" Алмазы ", (7, 7)), ("Пики", (8, 8)), ("Пики", (7, 7)), ("Алмазы", (2, 2)), ("Крест", (8, 8))]"
РЕДАКТИРОВАТЬ: теперь я понимаю значения параметров по умолчанию, и мне удалось решить мою первоначальную проблему. Спасибо тем, кто указал мне на решение. Однако одно из примененных мной решений работает, а другое - нет, хотя я думаю, что должно. (Я думаю, что это связано с исходной проблемой, поэтому я редактирую исходное сообщение, а не публикую новый вопрос.)
Так что это решение, которое сработало:
class Player():
def __init__(self,name,hand=None,balance=0):
self.name = name
self.hand = hand
if self.hand is None:
self.hand = []
for i in range(0,2):
self.hand.append( dealacard(usedcards))
self.balance = balance
... и это тот, который не сделал:
class Player():
def __init__(self,name,hand=None,balance=0):
self.name = name
self.hand = hand
if self.hand is None:
self.hand = emptyhand
for i in range(0,2):
self.hand[i] = dealacard(usedcards)
self.balance = balance
emptyhand - это в основном заполнитель, определенный вне класса Player:
emptyhand = [dummycard,dummycard,dummycard]
Поэтому, если я вызову переменную emptyhand после создания игрока, она также будет изменена и будет такой же, как и рука игрока. Таким образом, это не только не решает мою первоначальную проблему (все игроки в конечном итоге держат одну и ту же руку), похоже, что произошло какое-то обратное назначение, а пустая рука была изменена так же, как и рука игрока. Я знаю, что такого нет, но я не могу понять, что на самом деле здесь происходит.
Опять же, заранее спасибо за любые подсказки.