user3166776
user3166776

Reputation:

Tuple in list cannot be changed directly?

There's a programming problem for an online course which requires me to modify an item in a list of tuples. Strange, I know. Looking at some other questions on Stack Overflow, commenters have noted that a dictionary would make more sense.

However, data structures aside, the following code does not work:

l = [(0, 'apples'), (1, 'pears'), (2, 'bananas')]

for item in l:
    if item[0] == 1:
        item = 'something else'

Nope. It stays exactly the same. But when I write the loop differently, as:

for index in range(len(l)-1):
    if l[index][0] == 1:
        l[index] = 'what is this'

the middle item in the list is successfully changed, even though it is a tuple. I don't like the second piece of code; it seems unnecessarily verbose. Shouldn't it work either way? I'm considering reporting this behavior as a bug in Python (tried both 2.7 and 3.4).

Upvotes: 0

Views: 98

Answers (3)

Padraic Cunningham
Padraic Cunningham

Reputation: 180550

If you want to change inplace use enumerate not range:

l = [(0, 'apples'), (1, 'pears'), (2, 'bananas')]

for ind, tup in enumerate(l):
    if tup[0] == 1:
        l[ind] = "something else"
print(l)

Or you can use l[:] with a list comprehension to change the original list:

l[:] = ["something else" if tup[0] == 1 else tup for  tup in l]

print(l) 

Or use a generator expression:

l[:] = ("something else" if tup[0] == 1 else tup for  tup in l)

print(l)

item = 'something else' simply creates a variable item, actually indexing the list l[ind] and assigning a new value with = changes the item in the list.

As far as the the middle item in the list is successfully changed, even though it is a tuple goes, yes that is expected behaviour, you are changing an element in the list not an element in the tuple. If you try indexing the tuple and updating a value in that then it would be a different story, a TypeError: 'tuple' object does not support item assignment because tuples are immutable.

Upvotes: 3

Alex
Alex

Reputation: 19124

This is not a bug.

In the first example you are assigning a local variable name with item = 'something else'. Ie. item no longer refers to a tuple in the list. It is a new variable.

In the second example you are replacing elements in a list (which is mutable).

See Joran's answer for how you should do this.

Upvotes: 1

Joran Beasley
Joran Beasley

Reputation: 114108

items = [(0, 'apples'), (1, 'pears'), (2, 'bananas')]
print [item if item[0] != 1 else "something else" for item in items]

is normally how you would do this in python

Upvotes: 3

Related Questions