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 после создания игрока, она также будет изменена и будет такой же, как и рука игрока. Таким образом, это не только не решает мою первоначальную проблему (все игроки в конечном итоге держат одну и ту же руку), похоже, что произошло какое-то обратное назначение, а пустая рука была изменена так же, как и рука игрока. Я знаю, что такого нет, но я не могу понять, что на самом деле здесь происходит.

Опять же, заранее спасибо за любые подсказки.

0 ответов

Другие вопросы по тегам