FULL PYTHON FIX · 5 MIN READ
Why Does My Python Loop Keep Only the Last Item?
If each loop iteration assigns a new value to one variable, the earlier values disappear. Trace the variable, create a collection before the loop, and add each result to it.
Quick fix
Initialize results = [] before the loop.
names = ['Ada', 'Bo']
results = []
for name in names:
results.append(name.upper())
print(results)Video guide: Why Does My Python Loop Keep Only the Last Item?
The preview is stored on this site. YouTube loads only when you press Play. Watch on YouTube
Jump to a chapter
Read the video transcript
Select a timestamp to watch that moment on YouTube.
- 00:00
Imagine you want to uppercase every name in a list. The input contains Ada and Bo. A loop visits each name, calls upper, stores it in result, and prints result after the loop. What will the print call display? Many beginners expect two uppercase names because the loop did run twice. Let us actually execute it. The terminal prints only BO. This is a useful example of the difference between doing work on every iteration and keeping the work afterward. Python does not automatically collect values produced by a loop. The variable result holds just one value at a time. We will trace it after each iteration, change the program to accumulate values, and then test an empty input.
- 00:46
The same pattern explains why a report may contain only the last record, why a dictionary field keeps being replaced, or why a calculation returns just the final step instead of a history of results. Before editing the code, write down what should survive after the loop: one value, several displayed lines, or a reusable collection. Those are different goals and lead to different placements for print and append. The code begins with a list containing two strings. The for loop assigns a name on each pass. Inside the body, result equals name dot upper. On the first pass, name is Ada and result becomes ADA.
- 01:26
On the second pass, name is Bo and result becomes BO. The second assignment replaces the value held by the same variable. After the loop finishes, print sees the final value, BO. There is no hidden collection in result and no memory of the first uppercase string. If the print call were inside the loop, it would display both values on separate lines, but that still would not create a collection for later use. Move print outside again and confirm the one-value symptom. Knowing exactly when the assignment happens is more informative than focusing only on the final print. We can add a temporary trace inside the loop to make that sequence visible.
- 02:09
You can pause after each loop iteration and inspect result. The value changes from ADA to BO. That observation rules out a failure in upper and shows precisely which assignment discards the earlier value. In the diagnostic run, print the current input name and result on each iteration. You can see the transition from Ada to ADA, then Bo to BO. The loop is healthy: it visits both inputs. The bug is that assignment does not append to anything. A variable name points to the newest assigned value. Even though the expression calls a method on each input, its return value is saved only until the next assignment.
- 02:51
If you need all transformed values after the loop, decide what data structure represents that goal. An ordered list is appropriate here because you want one output for each input in the same order. Create the list before the loop, then add one item during each iteration. Be careful not to put the empty-list assignment inside the loop. If you reset the list on each pass, you will again keep only the last transformed name, this time wrapped inside a list. A trace print is temporary instrumentation. It can be removed after you understand the state change. If you need permanent records, append them to a collection or write them to a destination designed to preserve multiple values.
- 03:35
Place results equals an empty list before the for line. Inside the body, call results dot append with name dot upper. Now each pass changes the same list instead of replacing the variable with a single string. Run the corrected file. The output contains ADA and BO in that order. Trace the list to understand why: before the loop it is empty, after the first pass it contains ADA, and after the second it contains both names. The placement of the initialization matters as much as the append call. If you only wanted to display names, printing inside the loop might be enough. If you need to sort, count, save, or pass the transformed data to another function, collect it.
- 04:19
There is also a compact list comprehension that expresses the same mapping. Learn the explicit loop first; it makes the state change and the original bug easy to see. Append changes the list object and returns None. Do not assign results equals results dot append, because that would make results refer to None. Call append on its own line and inspect the list afterward. What should happen if the input contains no names? Run the corrected structure with an empty list. The loop body never executes, and results remains an empty list. Printing it shows empty square brackets rather than raising a NameError.
- 04:59
The broken version would fail in this situation because result would never be assigned at all. That is another reason to initialize the output before entering the loop. As an optional second form, write a list comprehension that calls upper for each name. It produces the same list, including the empty case. Now try a practice task: start with three numbers, double each one, and keep all three results for use after the loop. Predict the output, run it, and print the evolving list inside the loop only while debugging. Then remove the diagnostic print. If you see only the last doubled number, check whether you used assignment where you meant to append, or whether you reset the list inside the loop.
- 05:43
The Loops and Lists lessons on PythonLessonLab cover both operations in more depth. For the empty case, no assignment inside the loop runs, but the initialized list still exists. This edge case reveals why setup belongs before the loop. A comprehension also returns an empty list when it receives empty input.
Two items enter; one item leaves
The program below processes Ada and Bo, but prints only BO. The loop itself ran twice. The problem is the assignment to result: every pass replaces the previous value, and print runs only after the loop has finished.
This is a common symptom when building a transformed list, reading rows from a file, or collecting matches from a search. Python does not remember the previous value of a variable just because assignment happened inside a loop.
names = ['Ada', 'Bo']
for name in names:
result = name.upper()
print(result)BOTrace the assignment on every iteration
Move a diagnostic print inside the loop. After Ada, result is ADA. After Bo, result is BO. The second assignment does not add to the first; it binds the same name to a new string. Once the loop ends, only that final binding remains.
There is another edge case hidden in the broken version. If names is empty, the loop body never runs and result has never been assigned. Accessing it after the loop raises NameError. A correct accumulator should also have a sensible value for empty input.
names = ['Ada', 'Bo']
for name in names:
result = name.upper()
print(name, '->', result)Ada -> ADA
Bo -> BOCreate the list once, then append inside the loop
Initialize results = [] before the loop. That line must not be inside the loop, because doing so would reset the collection on every iteration. Call append() inside the loop to add one transformed name at a time.
Notice the different jobs of the variables: name holds the current input item, while results holds the accumulated output. Naming them differently makes an accidental overwrite easier to spot. The final print happens after the loop so the complete list is available.
names = ['Ada', 'Bo']
results = []
for name in names:
results.append(name.upper())
print(results)['ADA', 'BO']Test an empty list and compare a comprehension
Run the same pattern with no names. Because results was created before the loop, the output is the empty list rather than an exception. That test catches both a missing initialization and the mistaken placement of results = [] inside the loop.
Once the explicit loop is clear, a list comprehension expresses the same transformation in one line. Prefer the loop when you need to show intermediate steps or do more work per item. Do not write result = name.upper() and expect Python to accumulate automatically.
names = []
results = []
for name in names:
results.append(name.upper())
print(results)[]names = ['Ada', 'Bo']
results = [name.upper() for name in names]
print(results)['ADA', 'BO']- Initialize the output list before the loop.
- Append one result during each iteration.
- Test both multiple items and an empty input.
Practice the fix
Given prices = [5, 8, 11], create a list containing each price with 2 added. First use an explicit loop and append(); then rewrite it as a list comprehension. Check that an empty prices list gives [].
Need a hint?
Start with adjusted = [] outside the loop. Inside the loop call adjusted.append(price + 2). The comprehension's expression is price + 2.
Python console
Ready to runEdit the code and run it in your browser. Examples above can be loaded with Try this example.
Does your code use input()? Add one value per line
Your output appears here.
Key takeaways
- Assignment inside a loop replaces a variable's previous value.
- To keep every result, initialize a list before the loop and append inside it.
- Initializing inside the loop resets the collection repeatedly.
- An empty-input test reveals missing initialization; a comprehension is an optional concise form.