1

I am going to rewrite a list in a user-defined function, simply using the name of itself, rather than any built-in list function, but it doesn't work.

Using built-in functions(.append, del, etc) to mutate the list does work, but I still wonder why rewriting doesn't work. I simplify my code to show the main problem.

def function(y):
    y=y[:3]  # Rewrite the list
    return y


y=[0,1,2,3,4]
function(y)
print(y)

expected: [0,1,2] actual: [0, 1, 2, 3, 4]

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
mj li
  • 11
  • 2
  • "Why" questions are usually not a good fit for StackOverflow. The language works the way it does, because that's how it was designed. It's hard to answer beyond that. – Karl Knechtel Sep 29 '19 at 00:57
  • @CalebGoodman You shouldn't. Did you perhaps write `y = function(y)` instead? Or if you tried it statement by statement at the interpreter prompt, the `function(y)` line will produce `[0, 1, 2]` because the function `return`s that value, but the subsequent `print` will show `[0, 1, 2, 3, 4]` because, as OP describes, the global `y` has not been modified. – Karl Knechtel Sep 29 '19 at 00:59
  • @KarlKnechtel I modified the original code slightly without realized that it would change the results, and I deleted that comment after realizing – Lord Elrond Sep 29 '19 at 01:00
  • Anyway, I recommend reading: https://nedbatchelder.com/text/names.html – Karl Knechtel Sep 29 '19 at 01:20

1 Answers1

3

In fact the y in function and the y in the main function happen to have the same name, but are not the same variable, the are just a reference to the same object. but as soon as you make an assignment to y in the function you crate a new object

In order to make this more clear I renamed y in function() into yy

def function(yy):
    yy=yy[:3]  # Rewrite the list
    return yy


y=[0,1,2,3,4]
y = function(y) # here I assign the result of the function call to y
print(y)

Now A second solution, which might confuse you as it seems to contradict what I said before.

def function(yy):
    yy[:]=yy[:3]  # Rewrite the list

y=[0,1,2,3,4]
function(y) # here nothing is assigned. function directly modifies the passed object
print(y)

In fact following code in function y = y[:3] creates a new list, that contains the first three elements of y and assigns it to a variable, that will be called y, but which is a new object.

The code y[:] = y[:3] says to keep the same object y, but to replace all of its elements with the first three elements of y.

So again previous code, but now with debug prints:

def function(y):
    print("The id of y is ", id(y))
    y=y[:3]  # Rewrite the list
    print("The id of y is ", id(y)) # you created a new object
    return y


y=[0,1,2,3,4]
print("The id of y is ", id(y))
y = function(y) # here I assign the result of the function call to y
print(y)
print("The id of y is ", id(y))  # you got a new object, that is no stored in y

And now the other code with debug prints: def function(y): print("The id of y is ", id(y)) y[:]=y[:3] # Rewrite the list print("The id of y is ", id(y))

y=[0,1,2,3,4]
print("The id of y is ", id(y))
function(y) # here nothing is assigned. function directly modified the passed object
print("The id of y is ", id(y))
print(y)
gelonida
  • 5,327
  • 2
  • 23
  • 41