Right, I misread the code, my bad.
For this case, one should use a nested comprehension:
space = ((r, c, cell) for r, row in enumerate(table.rows) for c, cell in enumerate(row))
for (r, c, cell) in space:
if search_query.matches(cell.value):
logger.info("Found cell: (%s,%s)", r, c)
return (r, c)
Or see masklinn comment if you don't need the logger.
In all languages, you separate code for preparing your input and code for processing it. In python, it's also a good idea to do that at the loop level:
- prepare your stream of data so that it's normalized using itertools, generators, a function, a numpy array, etc
- do a single loop pass for your processing
This way you will you obtain a single iterable, and will be able to get the most out of the language tooling:
- you can pass it to map/filter, itertools or another comprehension
- you can convert to a list, a tuble, a Counter, etc. And slice it
- you can use "else" in the loop, which is an underused construct, but very useful when you need break
- you can use advanced unpacking
- you can call iter() and/or next(). This is what masklinn does in his example.
The point being, nested loops are rare enough, and we have tool to deal with them in an idiomatic way in Python, and not adding new syntax for a rare case that usually has a good solution makes sense to me.