I find this behaviour in Python quite peculiar and I believe it can lead to many bugs especially if you have a function/method that takes in a list and returns another list after carrying out some operations on the elements in list.x = []val = (row for row in x) # create a generatorprint(next(val)) # will raise StopIteration exceptionfor i in x:    if not i:        raise ValueError('The sequence is empty') # Exception is not raised    print(i) # does nothing and does not raise an exceptionIf you try to iterate over a generator with next and it's empty or has reached the end, a StopIteration exception is raised, but this is not the same when you use a for loop to iterate over a list or any iterable in Python.I know I could just write if not x: to check if the list is empty but I believe an  empty iterable should raise an Exception when you try to iterate over it as there is no benefit looping it.I want to know if there's any special reason for this behavior in the Language design or am I not considering another case where it might be useful. I think the same goes for Java too.
Why don't empty iterables in python raise Exceptions when you try to iterate over them
python;language design;language features;list;python 3.x
The thing that I think you're missing here is that the StopIteration is what actually makes the for loop stop.  This is why you can write custom iterators that work with Python's for loop transparently.  It doesn't do any checking to see if the iterator is empty, and the for loop does not keep track of of the iterator's state.  This is an effect of the iterator protocol, and was an intentional choice in the language design.  You can read more about the iterator protocol on Python's docs site if you want to.It also makes more sense if you think about the number of items in e.g. your list corresponding directly to the number of times your loop is executed.-----------------------------------|| No. of items | No. times executed|------------------------------------|      5       |         5         ||      4       |         4         ||      3       |         3         ||      2       |         2         ||      1       |         1         ||      0       |         0         |------------------------------------If the for loop special-cased an empty iterable, this invariant would be lost.It would also complicate the protocol on writing custom iterators, because you would have to have an extra method to signal to the for loop that your iterable is empty before the iteration began.Here's a (stupid) example of a custom iterator that always acts like it's empty:class EmptyIterator():    def __iter__(self): return self    def __next__(self): raise StopIterationfor blah in EmptyIterator():    print('this is never reached')try:    next(EmptyIterator())except StopIteration:    print('Oh hi, I was empty so I raised this Exception for you.')