Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Why not something like this:

  def f_iter(many, args):
      while True:
          m = f(many, args)
          if m:
              yield m
          else:
              raise StopIteration
  ...
  for m in f_iter(many, args):
      # do stuff with m
This way you’re isolating all the initialization logic, error handling, etc. And you can focus on your domain logic in your client code.


Python has built-in facilities for that, there is no need to write wrapper by yourself.

   from functools import partial
   with open('mydata.db', 'rb') as f:
       for block in iter(partial(f.read, 64), b''):
           process_block(block)


Instead of raising StopIteration you could also just return from the function. You could also make it a bit shorter if you swap the if branches.

  def f_iter(many, args):
      while True:
          m = f(many, args)
          if not m:
              return
          yield m


Instead of raising StopIteration you have to return from the function, otherwise you'll just get a RuntimeError starting with Python 3.7.


You're right. The [changelog] for Python 3.7 states:

> [bpo-32670]: Enforce [PEP 479] for all code. This means that manually raising a StopIteration exception from a generator is prohibited for all code, regardless of whether ‘from __future__ import generator_stop’ was used or not.

[changelog]: https://docs.python.org/3.7/whatsnew/changelog.html#id115

[bpo-32670]: https://bugs.python.org/issue32670

[PEP 479]: https://www.python.org/dev/peps/pep-0479/


And less reasonably, something similar for regular expressions:

    for m in filter([re.match(...)], bool):
        ...
;-)


so i should write a whole other function that iterates over a list instead of being happy that := exists?


Yes! No pain, no gain!




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: