Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary infinite loop is exiting unexpectedly

I was experimenting with various ways of creating an infinite loop in Python (other than the usual while True), and came up with this idea:

x = {0: None}  for i in x:     del x[i]     x[i+1] = None  # Value doesn't matter, so I set it to None     print(i) 

On paper, I traced out the way this would infinitely loop:

  1. I loop through the key's value in the dictionary
  2. I delete that entry.
  3. The current counter position in the loop + 1 will be the new key with value None which updates the dictionary.
  4. I output the current counter.

This, in my head, should output the natural numbers in a sort of infinite loop fashion:

0 1 2 3 4 5 . . . 

I thought this idea was clever, however when I run it on Python 3.6, it outputs:

0 1 2 3 4 

Yes, it somehow stopped after 5 iterations. Clearly, there is no base condition or sentinel value in the code block of the loop, so why is Python only running this code 5 times?

like image 361
Suraj Kothari Avatar asked Jan 22 '19 21:01

Suraj Kothari


People also ask

How do you fix an infinite loop in Python?

You can stop an infinite loop with CTRL + C . You can generate an infinite loop intentionally with while True . The break statement can be used to stop a while loop immediately.

Why is my for loop going Infinite?

An infinite loop occurs when a condition always evaluates to true. Usually, this is an error. For example, you might have a loop that decrements until it reaches 0.

CAN YOU DO FOR loop for dictionary?

You can loop through a dictionary by using a for loop. When looping through a dictionary, the return value are the keys of the dictionary, but there are methods to return the values as well.


2 Answers

There is no guarantee that you will iterate over all your dict entries if you mutate it in your loop. From the docs:

Iterating views while adding or deleting entries in the dictionary may raise a RuntimeError or fail to iterate over all entries.

You could create an "enumerated" infinite loop similar to your initial attempt using itertools.count(). For example:

from itertools import count  for i in count():     print(i)     # don't run this without some mechanism to break the loop, i.e.     # if i == 10:     #     break  # OUTPUT # 0 # 1 # 2 # ...and so on 
like image 168
benvc Avatar answered Nov 05 '22 03:11

benvc


In this case, like @benvc wrote, this is not guaranteed to work. But in case you wonder why does it work in C-Python:

The C-Python implementation destroys the dict object after some inserts and copies it to a new space in memory. It does not care about deletions. So when this happens, the loop notices it and breaking with an exception.

Check out this link if you want to read more about this, and many other interesting python internals here.

https://github.com/satwikkansal/wtfpython#-modifying-a-dictionary-while-iterating-over-it

like image 34
HWM-Rocker Avatar answered Nov 05 '22 05:11

HWM-Rocker