7

In C++, I often use the following pattern:

while (int i = getNextElementPlease()) {
    printf("%d\n", i);
}

But in python I have to repeat call twice:

i = getNextElementPlease()
while (i):
    print(i)
    i = getNextElementPlease()

How to avoid duplication of getNextElementPlease?

  • 1
    https://www.python.org/dev/peps/pep-0572/ – ayhan Dec 23 '18 at 11:10
  • @roganjosh Actually I am trying to call method `recv` of `multiprocessing.connection.Connection`, while there is not `None` element. –  Dec 23 '18 at 11:11
  • I was bout to make the same suggestion as schwobaseggl below. The problem afaik is that it's considered _unpythonic_ to write assignments in conditions of `while` and `if` (see the first comment [in this answer](https://stackoverflow.com/a/2603966/305949)). So, you cannot translate this to Python directly. – FK82 Dec 23 '18 at 11:15
  • @FK82 If it is unpythonic, it would be great to know what is pythonic way to do it. –  Dec 23 '18 at 11:17
  • @BhavinChirag `while True: ...` and `break` once your termination condition holds as described in both of the answers to your question. – FK82 Dec 23 '18 at 11:23

2 Answers2

10

Either with the classic while True/break pattern:

while True:
    i = getNextElementPlease()
    if not i:
        break
    ...

or by using the two-argument form of iter to build an iterator out of your function:

for i in iter(getNextElementPlease, sentinel):
    ...

where sentinel is whatever value you're expecting to terminate the loop. Probably something like None. The iterator will call getNextElementPlease to get elements and stop when getNextElementPlease returns the sentinel value.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • You can also define a `class AnyFalseValue:` whose `__eq__(self, other)` does `return not other`. Then using `iter(func, AnyFalseValue())` will be 100% equivalent of the `if not i: break`, catching both `None`, `False`, `0`, empty sequences etc. – Bakuriu Dec 23 '18 at 11:45
  • @Bakuriu: Doable, but at that point, it's probably clearer to switch to `while True`/`break`, or to write your own generator that calls an input function and stops when that function returns a false value. – user2357112 Dec 23 '18 at 11:51
8

Currently, the least repetitive version of this pattern (and often seen) is the following:

while True:
    i = getNextElementPlease()
    if not i:
        break
    print(i)

Looking ahead, however, Python 3.8 will introduce assignment expressions via pep-572 which will allow:

while i := getNextElementPlease():
    print(i)
user2390182
  • 72,016
  • 6
  • 67
  • 89