Empty anvil.tables.SearchIterator should be "False"

I some code like this:

rows = app_tables.qsessions.search(...)
if rows:
    <do something if more than 0 rows exist>  

However this fails because an empty iterator evaluates to True. To me this seems counterintuitive as an empty list (or similar) evaluates to False.

Of course this can be fixed by converting to a list but I might not need the rows. And it increases the cognitive burden.

1 Like

You can efficiently get the length of a search iterator with len():

if len(rows):
  # ... do something...

Yes, thanks. But wouldn’t you agree that the truthiness of an empty iterator should be False?

How does that compare to your experience with other iterators in Python?

Here’s what I get with a regular iterator:

>>> i = iter([1,2,3])
>>> bool(i)
True
>>> i = iter([])
>>> bool(i)
True

This is one thing that makes an iterator different from a container. An empty container is “falsy”. Virtually all other “objects” are “truthy”.

1 Like

Hmmm, hadn’t realised that. Thanks.
Is this the case for every iterator (by specification)?

As I understand it, by default, every Python object is “truthy”, except for a few, select cases:

  • None
  • False
  • Zero
  • Empty containers (including strings, tuples, sets, lists, dicts, …)
  • Objects of custom-built classes, if they were explicitly built to override that default

I’m not familiar with any such custom classes. I suspect they’re fairly rare.

Iterators are not among the exceptions, so they’re “truthy”.

Reference: Truth Value Testing

Edit: To be fair, it isn’t necessarily a bad idea. C++ has the concept of “empty ranges”, which test false when the range is exhausted. This method of stopping is handy in situations where Python’s exception-based approach (raise StopIteration when done) is too slow or bulky.

But there are situations where determining “emptiness” can be expensive. For example, an iterator backed by a network socket, and a buffer. If the buffer is empty, then the iterator might be “empty”; but that could change in a microsecond, as data arrives from across the network. In this case, Python’s iterator model, which is more general, looks to me like a better fit.

By now, there’s on the order of a billion lines of Python code that work under the above rules. Changing the rules now is probably not an option.

1 Like

Thx for the background info.