Python, кажется, рассматривает атрибут экземпляра как атрибут класса

Я хотел бы предварить это, сказав, что я очень новичок в Python и программировании в целом, поэтому вполне возможно, что я неправильно использую некоторые термины. Я пытаюсь сделать базовую версию карточной игры «Взрывающиеся котята» на Python. Я пытаюсь раздать карты из колоды (без котят, карты, которую вы хотите избежать рисования) экземпляру атрибута «рука» для каждого объекта класса Player, а затем удалить карту из колоды. Моя проблема в том, что я не могу сделать атрибут экземпляра вручную, чтобы он не выглядел так, как будто он действует как атрибут класса. Мой код и результат отображаются ниже:

import random

# Deck without kittens to deal out to the Players
deck_no_kittens = ["Attack","Attack","Attack","Attack","Steal","Steal","Steal","Steal","Favor","Favor","Favor","Favor","See the future","See the future","See the future","See the future","See the future","Alter the future","Alter the future","Shuffle","Shuffle","Shuffle","Shuffle","Skip","Skip","Skip","Skip"]

# Default starting hand for each player
start_hand = ["Defuse"]

class Player():
  def __init__(self, hand, alive, knowskitten):
    # Hand of each Player
    self.hand = hand
    # Determines if Player is alive
    self.alive = True
    # Determines if the Player knows if there is a kitten
    self.knowskitten = False

# Defines function that deals to Player while also removing it from deck_no_kittens
def deal(player):
  random_index = random.randint(0,len(deck_no_kittens)-1)
  card_to_add = deck_no_kittens.pop(random_index)
  player.hand.append(card_to_add)

# Initialize objects
computer1 = Player(start_hand, True, False)
computer2 = Player(start_hand, True, False)
user = Player(start_hand, True, False)

# Below is where my issue seems to be - the hand remains the same throughout each deal

# Deals 5 times, alternating, to computer1 and computer2, and prints the hand each time
for i in range(5):
  deal(computer1)
  print("\ncomputer1 hand is "+str(computer1.hand))
  deal(computer2)
  print("\ncomputer2 hand is"+str(computer2.hand))

# Prints deck_no_kittens
print("\n"+str(deck_no_kittens))

Результат:

computer1 hand is ['Defuse', 'Attack']

computer2 hand is['Defuse', 'Attack', 'Skip']

computer1 hand is ['Defuse', 'Attack', 'Skip', 'See the future']

computer2 hand is['Defuse', 'Attack', 'Skip', 'See the future', 'Steal']

computer1 hand is ['Defuse', 'Attack', 'Skip', 'See the future', 'Steal', 'Skip']

computer2 hand is['Defuse', 'Attack', 'Skip', 'See the future', 'Steal', 'Skip', 'Attack']

computer1 hand is ['Defuse', 'Attack', 'Skip', 'See the future', 'Steal', 'Skip', 'Attack', 'Attack']

computer2 hand is['Defuse', 'Attack', 'Skip', 'See the future', 'Steal', 'Skip', 'Attack', 'Attack', 'Shuffle']

computer1 hand is ['Defuse', 'Attack', 'Skip', 'See the future', 'Steal', 'Skip', 'Attack', 'Attack', 'Shuffle', 'Favor']

computer2 hand is['Defuse', 'Attack', 'Skip', 'See the future', 'Steal', 'Skip', 'Attack', 'Attack', 'Shuffle', 'Favor', 'Shuffle']

['Attack', 'Steal', 'Steal', 'Steal', 'Favor', 'Favor', 'Favor', 'See the future', 'See the future', 'See the future', 'See the future', 'Alter the future', 'Alter the future', 'Shuffle', 'Shuffle', 'Skip', 'Skip']

Я ожидал, что каждая рука для каждого объекта будет разной, но каждая сделка добавляет универсальную руку. Любая помощь/предложения приветствуются.

У вас есть разные списки для каждого объекта класса, который вы создали, но списки не собираются волшебным образом стираться без явного указания python сделать это.

Chris 16.04.2019 14:57
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
45
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Оба атрибута экземпляра hand являются ссылками на один и тот же список, поэтому, когда этот список изменяется, это влияет на оба.

Простым решением было бы скопировать список в __init__ вашего класса:

from copy import copy

class Player():
  def __init__(self, hand, alive, knowskitten):
    # Hand of each Player
    self.hand = copy(hand)
    # Determines if Player is alive
    self.alive = True
    # Determines if the Player knows if there is a kitten
    self.knowskitten = False
Ответ принят как подходящий

Проблема здесь в том, что вы используете один и тот же «объект» start_hand для создания обоих игроков. Вы сохраняете ссылку на тот же список start_hand во внутренней переменной hand.

Когда вы вносите изменения в hand в одном игроке - другой игрок может это увидеть.

Чтобы решить эту проблему, создайте новый список.

self.hand = list(start_hand)

или просто self.hand = hand[:]

han solo 16.04.2019 14:57

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