0

Below is a simplified version of my problem:

example =[
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0]
    ]

def func(data):
    data[0][0:6] = [1, 1, 1, 1, 1]
    data[1][0:6] = [1, 1, 1, 1, 1]
    return data    

print(example)
func(example)
print(example)

and has the output:

[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
[[1, 1, 1, 1, 1], [1, 1, 1, 1, 1]]

The output I am expecting is:

[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]

How do I avoid the global variable "example" from being updated after running "func"? I have tried a number placeholder variable combinations (inside and outside "func") and all have the same result - an updated "example".

PBKyle
  • 1

4 Answers4

1

While you should avoid using globals, if you absolutely need to do the above, use deepcopy():

from copy import deepcopy

example =[
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0]
    ]

def func(data):
    data = deepcopy(data)
    data[0][0:6] = [1, 1, 1, 1, 1]
    data[1][0:6] = [1, 1, 1, 1, 1]
    return data

print(example)
func(example)
print(example)
Aziz Sonawalla
  • 2,482
  • 1
  • 5
  • 6
0

Try using deep copy:

import copy
example =[
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0]
    ]

def func(data):
    data[0][0:6] = [1, 1, 1, 1, 1]
    data[1][0:6] = [1, 1, 1, 1, 1]
    return data    

print(example)
func(copy.deepcopy(example))
print(example)
Pinyi Wang
  • 823
  • 5
  • 14
0

Because lists are mutable, they are basically passed by reference to func. If you want to act on a different copy of that object, you need to explicitly make such a copy (other answers say the same, but for your case you probably want that inside the function):

import copy

example =[
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0]
    ]

def func(data):
    localdata = copy.deepcopy(data). ## or data.copy() or copy.copy(data)
    localdata[0][0:6] = [1, 1, 1, 1, 1]
    localdata[1][0:6] = [1, 1, 1, 1, 1]
    return localdata    

print(example)
newexample = func(example)
print(example)

Whether you want copy.copy(data) or copy.deepcopy(data) or data.copy() depends on what you know about the input.

Note also that your original code doesn't use its return for anything...

Andrew Jaffe
  • 26,554
  • 4
  • 50
  • 59
  • Python argument passing mechanics don't change depending on whether the argument is mutable. (If it looks like they do, that's because of the operations you're testing. Comparisons like `x = 3` vs `y[0] = 4` are misleading - `y[0] = 4` isn't an assignment to `y`.) – user2357112 May 27 '20 at 22:23
  • @user2357112supportsMonica That is correct, of course, but I didn't feel it was particularly helpful to go into the semantics of Python name binding which underlies all of this. – Andrew Jaffe May 27 '20 at 22:29
0

You need to make a copy for this to work. And since example is a list of lists, you have to either use copy.deepcopy() or list comprehensions, like the following:

example =[
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0]
    ]

def func(data):
    dataCopy = [sublist.copy() for sublist in data]
    dataCopy[0][0:6] = [1, 1, 1, 1, 1]
    dataCopy[1][0:6] = [1, 1, 1, 1, 1]
    return dataCopy    

print(example) # all 0's
func(example)
print(example) # still all 0's

print(func(example)) # all 1's
jdaz
  • 5,964
  • 2
  • 22
  • 34