Python Forum
[HELP] Function that changes its entrances
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[HELP] Function that changes its entrances
#1
Hello everyone,

I struggle with a python code. I found the problem and reproduced the condition of its occurence in the following lines:

def PLS(A):
    B = A
    B[0] = B[2]
    return(B)
    
A = [1,2,3]
D = PLS(A)
print(A)
Compiling those few lines, I expect D to be [2,3,2] and A to be [1,2,3].
Yet I get D = A = [2,3,2]

Why does the code modify the A list?
And how can I stop it from doing so?

I'm really thankful for any help, I've been stuck for a while on that :D
Reply
#2
It would help us if you could use code tags (select code lines and click the blue/yellow python icon).

Your issue is that lists are assigned by reference so the line B = A means both B and A will point to the same memory location. If you want them to stay independent you can use the list slice notation:
def PLS(A):
    B = A[:] # Taking a slice with no indexes grabs the whole list but makes an actual copy.
    B[0] = B[2]
    return(B)
"So, brave knights, if you do doubt your courage or your strength, come no further, for death awaits you all with nasty, big, pointy teeth!" - Tim the Enchanter
Reply
#3
Hey Liquid,
I am not sure why this error is happening but you can fix it by redefining A:
def PLS(A):
  B = A
  B[0] = B[2]
  return(B)

A = [1,2,3]
D =  PLS(A)
A = [1,2,3]
print(A)
Reply
#4
This does not make a copy of the list, it makes two variables that both point to the same list.
a = [1, 2, 3]
b = a
print(id(b), id(a))
Output:
2504484054272 2504484054272
You can tell the two are the same list because both point to the same Python object (2504484054272)

If you want your PLS function to return a modified copy of the provided list, you first need to make a copy. In the code below I do this using [:] which makes a new list with the same contents as the original list.
def PLS(A):
  B = A[:]
  B[0] = B[2]
  return(B)
 
A = [1,2,3]
D =  PLS(A)
A = [1,2,3]
print(A, D)
print(id(A), id(D))
Output:
[1, 2, 3] [3, 2, 3] 1820201877184 1820196404928
The result is now what you want, and you can see from the object ID that you have two different lists

Another way to make a copy of a list is use copy.
import copy

def PLS(A):
  B = copy.copy(A)
  B[0] = B[2]
  return(B)
Reply
#5
(Aug-07-2020, 09:03 PM)deanhystad Wrote: This does not make a copy of the list, it makes two variables that both point to the same list.
a = [1, 2, 3]
b = a
print(id(b), id(a))
Output:
2504484054272 2504484054272
You can tell the two are the same list because both point to the same Python object (2504484054272)

If you want your PLS function to return a modified copy of the provided list, you first need to make a copy. In the code below I do this using [:] which makes a new list with the same contents as the original list.
def PLS(A):
  B = A[:]
  B[0] = B[2]
  return(B)
 
A = [1,2,3]
D =  PLS(A)
A = [1,2,3]
print(A, D)
print(id(A), id(D))
Output:
[1, 2, 3] [3, 2, 3] 1820201877184 1820196404928
The result is now what you want, and you can see from the object ID that you have two different lists

Another way to make a copy of a list is use copy.
import copy

def PLS(A):
  B = copy.copy(A)
  B[0] = B[2]
  return(B)


Aahh! Thank you a lot. That's different from languages I'm used to. I naively thought using a different variable name would lead to the duplication of the data set.
Damn, I have 1k lines of code waiting to be changed now :D

Thank you for your kind help!
Reply
#6
In Python a variable is really nothing more than a name used to reference something, an entry in the namespace. I guess you could say that about all languages, but in Python there is no compiler preventing us from reusing the same variable to refer to different things. This is perfectly valid Python but would give C conniptions:
def myfunc(a):
    return a
myvar = myfunc
myvar = myvar(1234)
myvar = str(myvar)
myvar = [int(c) for c in myvar]
Reply
#7
Do you have any thoughts on my Machine Learning problem?
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020