2

A function is overwitting a variable which is given it as an argument. Why?

What is this whole code supposed to do:

  • create a list (main deck) of objects representing cards
  • create an empty list for storage od the ids of cards already drawn from the main deck
  • choose randomly 5 cards from the main deck and add them to the list (player's deck)
  • return temp list of ints (ids of cards in the main deck) to a variable
  • add items from the temp list to the main list

        import random
    
        from common import cards
    
        deck = cards.deck()  # creates a list of 52 class objects representing cards
    
    
        def main():
            used_cards_ids = []  # this one is being overwritten in the next step, according to the debugger
    
            players_deck, temp_used_cards_ids = generate_players_deck(used_cards_ids)  # this is the "next step"
            used_cards_ids.extend(temp_used_cards_ids)  # adds id of the cards which were drawn from the main deck
    
            print(used_cards_ids)  # prints a double list of cards ids (i.e 1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
    
    
        def generate_players_deck(temp_used_cards_ids):
            players_deck = []
            counter = 0
    
            while counter < 5:  # until 5 cards were drawn
                cards_id = random.randint(0, 51)  # chooses a random card
                if cards_id not in temp_used_cards_ids:  # checks if the card with the same id weren't previously drawn
                    counter += 1
                    temp_used_cards_ids.append(cards_id)  # adds card's id to the list of drawn cards
                    players_deck.append(deck[cards_id])  # adds card to the player's deck
                else:
                    continue
    
            return players_deck, temp_used_cards_ids  # returns player's deck (list of cards objects) and list of ids of the drawn cards
    
    
        main()
    
  • 2
    Can you provide more detail on what the issue is? What variable is it overwriting that you don't expect? – user1558604 Dec 03 '19 at 03:39
  • 1
    If you mean it's overwriting `used_cards_ids`, as I'm guessing from the description of your question, it appends data to it in the function when you pass in `used_cards_ids`. Then you extend it afterwards with itself, because you return it as the `temp_used_cards_ids` argument. – dddJewelsbbb Dec 03 '19 at 03:43
  • 1
    Are you under the impression that functions get copies of all their arguments? They don't. Python isn't a pass-by-value language. – user2357112 Dec 03 '19 at 03:43
  • Primitive types (e.g. int, str, NOT list) are passed by value, but nothing else. Technically python is a pass by object-reference language (https://stackoverflow.com/a/33066581/6685140) – Sam Hollenbach Dec 03 '19 at 03:56
  • @user1558604 "used_cards_ids" this one. At the point when python prints it, the result is twice the number of given ids. It seems like at this point: "used_cards_ids.extend(temp_used_cards_ids)" the "used_cards_ids" is already filled with some characters, although IMO it should be empty. – Mateusz Chruściel Dec 03 '19 at 04:06
  • @dddJewelsbbb Yes! Yes it does this very thing. But why does it do that? I can't get it. At which moment does it "append data to it in the function when you pass in "used_cards_ids""? – Mateusz Chruściel Dec 03 '19 at 04:10
  • @user1558604 No, the other comments did not anwser my question, but actually dddJewelsbbb got the closest to it. I know python does the exact thing dddJewelsbbb written, but I can't get why. – Mateusz Chruściel Dec 03 '19 at 04:11
  • Take a look at this for the differnce between deep and shallow copy. https://stackoverflow.com/questions/17246693/what-is-the-difference-between-shallow-copy-deepcopy-and-normal-assignment-oper/17246744#17246744 – user1558604 Dec 03 '19 at 04:14

1 Answers1

1

When you pass in used_cards_ids to generate_players_deck(), you are providing the body of generate_players_deck() to append data to used_cards_ids, which you've aliased to temp_used_cards_ids.

You then get the value back from the return statement of that function, which you store in the variable temp_used_cards_ids, and then you extend that temp_used_cards_ids, which is actually used_cards_ids, essentially altering the list you passed in twice.

When you pass a list as a function argument, you aren't passing the values of the list, you're passing a reference to the original list. That's probably where your confusion is coming from, or perhaps the switch between variable names and function argument aliasing.

dddJewelsbbb
  • 626
  • 4
  • 17