4

I'm working on a homework assignment and I'm running into a weird issue with python I don't quite understand. I am creating an abacus based on some input number and to do this I created a base abacus or an "empty" abacus representing 0 as a global variable. In my function I set the new_abacus value equal to the empty_abacus global variable; but for some reason when I change the new_abacus variable the empty_abacus variable also changes.

Inside my function:

def function(input_num):  
  global empty_abacus
  new_abacus = empty_abacus 

  #I then change the new_abacus variable

  return new_abacus

When I try printing out empty_abacus after using this function it has been changed. I assume this is some weird thing with global variable in pythons. How can I prevent empty_abacus from being changed when I change new_abacus. Or in other words, how can I assign new_abacus the value of empty_abacus; rather than a reference.

Note: empty_abacus is a 2-dimensional list

EDIT: I apologize if the title is misleading, I'm not sure how to put it in words.

J Velvet
  • 85
  • 6
  • 2
    What is the type of `empty_abacus`? Assigning it to another name will not create a copy, and if it's mutable, changes will be reflected on the original copy. – iz_ Sep 03 '19 at 18:24
  • Its a 2 dimensional list – J Velvet Sep 03 '19 at 18:24
  • 1
    Now, people, _this_ is how you should ask a homework assignment question. – bereal Sep 03 '19 at 18:26
  • 2
    I'm not sure you need `global empty_abacus`, since you aren't trying to mutate `empty_abacus`, just get a copy. I'd do `new_abacus = copy.deepcopy(empty_abacus)`, where `deepcopy` will return exactly that, a deeply copied (but new) object – C.Nivs Sep 03 '19 at 18:28
  • Use the [`copy`](https://docs.python.org/3/library/copy.html#module-copy) module to make a copy. – martineau Sep 03 '19 at 18:30
  • One key piece of knowledge that you need here is: in Python, assignment *never* copies data. See https://nedbatchelder.com/text/names.html – jarmod Sep 03 '19 at 18:36

2 Answers2

2

The crux of your issue here is new_abacus = empty_abacus, which doesn't perform how you think it would. empty_abacus is passed by reference, which means that both new_abacus and empty_abacus will point to the same position in memory. Changes to one of the two will affect the same space in memory.

Instead, make a copy of empty_abacus within new_abacus:

import copy

# ... other code here ...

new_abacus = copy.deepcopy(empty_abacus)
esqew
  • 42,425
  • 27
  • 92
  • 132
  • Thank you for the concise answer. I'm very used to c++ where everything pretty much everything copies by value unless you specify otherwise. Python is a big change from that. – J Velvet Sep 03 '19 at 18:34
  • If you dont want your `empty_abacus` to change, then you need to remove the statement `global empty_abacus` from your function. – lpozo Sep 03 '19 at 18:35
0

new_abacus = empty_abacus

This line does not make copy of the variable instead refer it as same variable.

You need to create another copy of variable depending upon the data type: Some like this makes it more clearer: Copied variable changes the original?

As mentioned in the comments: new_abacus = copy.deepcopy(empty_abacus)

This will create a another copy so you are not refering to same object in the memory

Jaskaran Singh
  • 531
  • 3
  • 14