0

In a for-loop I attempt to overwrite string-type variables.

item1 = "Item 1"
item2 = "Item 2"
for item in [item1, item2]:
    if item == "Item 2":
        item = "Item 1"
print (item1, item2)

The print that results says "Item 1 Item 2". It should say "Item 1 Item 1"

I also tried item = item.replace("Item 2","Item 1"). Same result.

What prevents "Item 2" from getting replaced?

Update:

Similar to Changing iteration variable inside for loop in Python but with strings, not integers.

I have a much longer list of variables to validate and overwrite, so a for-loop that just uses the current item for reassignment would be ideal (as opposed to item2 = "Item 1")

Community
  • 1
  • 1
Spencer H
  • 653
  • 3
  • 12
  • 30
  • Possible duplicate of http://stackoverflow.com/questions/15363138/scope-of-python-variable-in-for-loop btw you cannot change value of loop variable which is elaborated in the link. – Ganesh Kathiresan Mar 24 '17 at 15:27
  • 1
    I'm not sure why you think your loop should do what you think it should do. You never reassign `item1` or `item2`, so why are you confused that they have not changed? – timgeb Mar 24 '17 at 15:27
  • 1
    Dup of http://stackoverflow.com/questions/4081217/how-to-modify-list-entries-during-for-loop. – CristiFati Mar 24 '17 at 15:29
  • [Clear explanation of variable referencing](http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference) – Casper Mar 24 '17 at 15:30
  • 1
    Guys, this is not a duplicate of a "change list while iterating over it" question. The central point here is that OP does not understand how assignment works. – timgeb Mar 24 '17 at 15:30
  • use item2 = "Item 1" in the if block. – plasmon360 Mar 24 '17 at 15:32
  • @timgeb The goal is to iterate through a list of variables and replace specific variable contents if they meet the if condition. Is a for-loop not the best choice? – Spencer H Mar 24 '17 at 15:32
  • @SpencerH. The problem here is that you never replace what's in `item1` or `item2` because you never use it. If you -for example- want to change what `item1` references to you MUST write `item1 = ...`. – timgeb Mar 24 '17 at 15:36
  • 1
    To be more precise, you are tripping over the fact that "Names are reassigned independently of other names." https://nedbatchelder.com/text/names.html – timgeb Mar 24 '17 at 15:41
  • I could easily do this without a for-loop using just `item2 = "Item 1"`. That would defeat the purpose. The goal (if it is feasible) is to iterate through several variables at once and overwrite values based on the current item in the iteration. – Spencer H Mar 24 '17 at 15:44
  • think of these more as 'names that refer to values'. The loop creates a new name which it assigns items from the iterable, one by one. Changing what that name refers to has no effect on the values your original names refer to. Probably easiest if you review your usual suspects of python tutorials on this – pvg Mar 24 '17 at 15:47
  • Then you would just change that list entry, not the variable. – Kenny Ostrom Mar 24 '17 at 15:47

1 Answers1

4

You're re-assigning the temporary variable item which is assigned on every iteration of the for-loop. So basically, you re-assign item to "Item 1" and then the interpreter immediately re-assigns it again on the next iteration to "Item 2". In any case, however, you are never mutating the original list by re-assigning this variable.

If you really want the last line to print what you want, then you want to re-assign your original variables instead:

item1 = "Item 1"
item2 = "Item 2"
for item in [item1, item2]:
    if item == "Item 2":
        item2 = "Item 1"
print (item1, item2)

It makes more sense however to make a list of the changes, though. This is the common pattern:

old_list = ["Item 1", "Item 2"]
new_list = []
for item in old_list:
    if item == "Item 2":
        new_list.append("Item 1")
    else:
        new_list.append(item)

print new_list
Julien
  • 5,243
  • 4
  • 34
  • 35
  • There's a builtin for this "map" – Kenny Ostrom Mar 24 '17 at 15:53
  • It's a style choice, for something this simple. I personally consider defining a new function or writing a lambda function here as less elegant. If anything, a list comprehension might be the next step here, but with this example even that's pretty weird. – Julien Mar 24 '17 at 15:59