(1) I dare say this is less readable than the original. Not
un-readable, but definitely less readable. Just put them side-by-side if this isn't obvious.
(2) You probably don't want to call it something generic like "flatten" if it's going to do something so specific like concatenate table.rows. Note that I'm not just nitpicking on the name here. Rather, my bigger point is your factored-out functions aren't really as reusable as your name suggests. In this particular case you can trivially get around it by passing table.rows directly, but that obviously wouldn't generalize if you needed anything else in the table in the process.
> This process is generalizable
(3) I'd question that too. Imagine if you had a per-row operation too. Like maybe:
found = None
for r, row in enumerate(table.rows):
for c, cell in enumerate(row):
if search_query.matches(cell.value):
found = (r, c)
break 2
logger.log("Finished row #{}".format(r + 1))
Are you really going to factor it out like this?
def flatten(table):
for r, row in enumerate(table.rows):
for c, cell in enumerate(row):
yield (r, c, row, cell)
logger.log("Finished row #{}".format(r + 1))