0

Hello I was creating a small test script for black jack, and while using the OOP, I found it returns same value for two different instances

import random

color=['Hearts', 'Diamonds', 'Spades', 'Clubs']
shape=['Jack', 'Queen', 'King']
deck={}
for x in color:
    for i in range(1,11):
        commpination=str(i)+" "+x
        deck[commpination] = i
    for y in shape:
        commpination=y+" "+x
        deck[commpination] = 10
class Player:
    def __init__(self,name='Dealer',money=0,bet=0,player_cards=[],player_value=0):
        self.name=name
        self.money=money
        self.bet=bet
        self.player_cards=player_cards
        self.player_value=player_value

    def hit(self):
        global deck
        #here will choose random card from the cards and add it to the player deck, 
        #will return Random key and put it in the new_card list
        new_card=random.choice(list(deck.keys()))
        #remove the choosen card from the deck
        deck.pop(new_card)
        self.player_cards.append(new_card)

ahmed=Player('Ahmed',200,20)    # create new instance called Ahmed
sara=Player()                   # create new instance called Sara
ahmed.name                      # outputs 'Ahmed'
mohamed.name                    # outputs 'Dealer'
ahmed.hit()                     # run the method on ahmed
ahmed.player_cards              # returns '5 Hearts'
mohamed.player_cards            # returns '5 Hearts'

My question is why mohamed.player_cards returns '5 Hearts' without first running mohamed.hit() and that with everything in my script, whenever I run method on the first instance I found second instances modified too?

kaya3
  • 47,440
  • 4
  • 68
  • 97

1 Answers1

2
>>> sara.player_cards is ahmed.player_cards
True

The [] default value is evaluated once when defined, so both instances reference the same list.

Use None as default instead.

class Player:
    def __init__(self,name='Dealer',money=0,bet=0,player_cards=None,player_value=0):
        self.name=name
        self.money=money
        self.bet=bet
        self.player_cards=player_cards if player_cards is not None else []
        self.player_value=player_value

Often you can get away with testing for any 'falsy' value rather than None explicitly (see Is there shorthand for returning a default value if None in Python?)

        self.player_cards=player_cards or []
Pete Kirkham
  • 48,893
  • 5
  • 92
  • 171