The intent of that code isn't immediately obvious. Sure people would understand it after a while, but the code could be made clearer.
The solution I offer requires more lines of code, but that code is in a class that can be stored elsewhere. In addition this solution will work for iterables and iterators as well as sized containers.
Your code would be changed to:
it = HadItemsIterable(data)
for x in it:
...
if it.had_items:
...
The code for the class is as follows:
from collections.abc import Iterable
class HadItemsIterable(Iterable):
def __init__(self, iterable):
self._iterator = iter(iterable)
@property
def had_items(self):
try:
return self._had_items
except AttributeError as e:
raise ValueError("Not iterated over items yet")
def __iter__(self):
try:
first = next(self._iterator)
except StopIteration:
if hasattr(self, "_had_items"):
raise
self._had_items = False
raise
self._had_items = True
yield first
yield from self._iterator
data
a list or other such container? – Leitmotifdata
is a list, why not useif not data:
? – Leitmotifx
, which is unusual since we just setx
: what is going on? (3) The test at the end does not work if the last element ofdata
isobject()
: is this intended? can this happen? are we really testing for the emptiness ofdata
? (4) The test intended to say "is data empty " actually reads "is x empty". Another reason why it is complicated is that there is a simpler solution (see my answer). :) – Zipporahobject()
creates a new object (it's not a singleton). – Zipporah