2

I've been learning python for some time, but it keeps suprising me.
I have following code:

def update_list(input_list):
    input_list.append(len(input_list))
    input_list[0] = 11
    return input_list

def update_string(input_string):
    input_string = 'NEW'
    return input_string


my_list = [0,1,2]

print my_list
print update_list(my_list)
print my_list


my_string = 'OLD'

print my_string
print update_string(my_string)
print my_string

This code provides following output:

[0, 1, 2]
[11, 1, 2, 3]
[11, 1, 2, 3]
OLD
NEW
OLD

Why variable my_list is modified without attribution, and my_string value stays the same after update_string() function? I don't understand that mechanism, can you explain it to me?

1
  • Just read about lists and strings in python and how some variables are mutable and other are unmutables. Also, in your 'update_string' function, you're creating a new LOCAL variable, you're not modifying the variable outside your function. Commented Jan 11, 2016 at 18:32

1 Answer 1

3

There is nothing different about the behaviour of functions. What is different is that in one of them you rebound the name:

input_string = 'NEW'

This sets the name input_string to a new object. In the other function you make no assignments to a name. You only call a method on the object, and assign to indices on the object. This happens to alter the object contents:

input_list.append(len(input_list))
input_list[0] = 11

Note that assigning to an index is not the same as assigning to a name. You could assign the list object to another name first, then do the index assignment separately, and nothing would change:

_temp = input_list
_temp[0] = 11

because assigning to an index alters one element contained in the list, not the name that you used to reference the list.

Had you assigned directly to input_list, you'd have seen the same behaviour:

input_list = []
input_list.append(len(input_list))
input_list[0] = 11

You can do this outside a function too:

>>> a_str = 'OLD'
>>> b_str = a_str
>>> b_str = 'NEW'
>>> a_list = ['foo', 'bar', 'baz']
>>> b_list = a_list
>>> b_list.append('NEW')
>>> b_list[0] = 11
>>> a_str
'OLD'
>>> b_str
'NEW'
>>> a_list
[11, 'bar', 'baz', 'NEW']
>>> b_list
[11, 'bar', 'baz', 'NEW']

The initial assignments to b_str and b_list is exactly what happens when you call a function; the arguments of the function are assigned the values you passed to the function. Assignments do not create a copy, they create additional references to the object.

If you wanted to pass in a copy of the list object, do so by creating a copy:

new_list = old_list[:]  # slicing from start to end creates a shallow copy
Sign up to request clarification or add additional context in comments.

5 Comments

I don't understand - what is the difference between my_list[0]=11 and my_string='new'? Isn't that the same operation?
@Djent: not quite. Do you understand the difference between my_list = 11 and my_list[0] = 11? Or, for that matter, my_dict = {}, my_dict['key'] = 'value'?
@Djent: the difference is one of where the reference to the object is stored; my_string = 'new' stores a reference to a string object in the variable my_string, where the variables all live together as port of the function scope. my_list[0] = 11 stores a reference to an integer in a list. You can assign to other indexes in that list, but you can't assign to names in that list.
ok, now I understand. Can you tell me how can I know which actions create reference to variable, and which ones will create copy?
@Djent: assignment never creates a copy. You always make a copy explicitly. So foo = bar is always a reference. It is the expression on the right-hand side that may or may not create a copy. Strings are immutable, so the only thing a method on a string object can do is to create a new string to return. List objects are mutable, you can alter their contents, so methods usually do so and return None. Read the documentation for each object type to determine how they behave.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.