What's the difference between “while 1” and “w

2019-02-05 19:00发布

问题:

I've seen two ways to create an infinite loop in Python:

  1. while 1:
        do_something()
    
  2. while True:
        do_something()
    

Is there any difference between these? Is one more pythonic than the other?

回答1:

Fundamentally it doesn't matter, such minutiae doesn't really affect whether something is 'pythonic' or not.

If you're interested in trivia however, there are some differences.

  1. The builtin boolean type didn't exist till Python 2.3 so code that was intended to run on ancient versions tends to use the while 1: form. You'll see it in the standard library, for instance.

  2. The True and False builtins are not reserved words prior to Python 3 so could be assigned to, changing their value. This helps with the case above because code could do True = 1 for backwards compatibility, but means that the name True needs to be looked up in the globals dictionary every time it is used.

  3. Because of the above restriction, the bytecode the two versions compile to is different in Python 2 as there's an optimisation for constant integers that it can't use for True. Because Python can tell when compiling the 1 that it's always non-zero, it removes the conditional jump and doesn't load the constant at all:

    >>> import dis
    >>> def while_1():
    ...     while 1:
    ...         pass
    ...
    >>> def while_true():
    ...     while True:
    ...         pass
    ...
    >>> dis.dis(while_1)
      2           0 SETUP_LOOP               5 (to 8)
    
      3     >>    3 JUMP_ABSOLUTE            3
                  6 POP_TOP
                  7 POP_BLOCK
            >>    8 LOAD_CONST               0 (None)
                 11 RETURN_VALUE
    >>> dis.dis(while_true)
      2           0 SETUP_LOOP              12 (to 15)
            >>    3 LOAD_GLOBAL              0 (True)
                  6 JUMP_IF_FALSE            4 (to 13)
                  9 POP_TOP
    
      3          10 JUMP_ABSOLUTE            3
            >>   13 POP_TOP
                 14 POP_BLOCK
            >>   15 LOAD_CONST               0 (None)
                 18 RETURN_VALUE
    

So, while True: is a little easier to read, and while 1: is a bit kinder to old versions of Python. As you're unlikely to need to run on Python 2.2 these days or need to worry about the bytecode count of your loops, the former is marginally preferable.



回答2:

The most pythonic way will always be the most readable. Use while True:



回答3:

It doesn't really matter. Neither is hard to read or understand, though personally I'd always use while True, which is a bit more explicit.

More generally, a whole lot of while–break loops people write in Python could be something else. Sometimes I see people write i = 0; while True: i += 1 ..., which can be replaced with for i in itertools.count() and people writing while True: foo = fun() if foo is None: break when this can be written for foo in iter(fun, None), which requires learning but has less boilerplate and opportunity for silly mistakes.



回答4:

Neither.

Both of them mean I have to scan the code looking for the break, instead of being able to see the stop condition right where it belongs.

I try to avoid this kind of thing wherever possible, and if it's not possible, let the code speak for itself like this:

while not found_answer:
    check_number += 1
    if check_number == 42:
        found_answer = True

Edit: It seems that the word "avoid" above wasn't clear enough. Using a basically infinite loop and leaving it from somewhere within the loop (using break) should usually be avoided altogether. Sometimes that isn't possible. In that case, I like to use something like the code above, which, however, still represents the same conceptthe above code is nothing more than a compromise – but at least, I can show the purpose of the loop at the beginning – just like I wouldn't call a function do_something_with_args(*args).



回答5:

I think this is mostly a matter of style. Both should be easily understandable as an infinite loop.

However, personally I prefer the second option. That's because it just takes a mental micro-step less to understand, especially for programmers without C background.



回答6:

The first one will work also in those early versions where True is not yet defined.



回答7:

If you have an algorithm that is suppose to terminate in a finite time, I would recommend this, which is always safer than while True:

maxiter = 1000
for i in xrange(maxiter):
   # your code
   # on success:
     break
else:
   # that algorithm has not finished in maxiter steps! do something accordingly


回答8:

IMO the second option is more obvious.

If you could get rid of the while and write more compact code, that might be more pythonic.
For example:

# Get the even numbers in the range 1..10
# Version 1
l = []
n = 1
while 1:
    if n % 2 == 0: l.append(n)
    n += 1
    if n > 10: break
print l

# Version 2
print [i for i in range(1, 11) if i % 2 == 0]

# Version 3
print range(2, 11, 2)


回答9:

I believe the second expression is more explicit, and thus more pythonic.



回答10:

This is only a matter of style, any programming beginner will understand either option.

But the second option will only work if True wasn't assigned to False, which was possible until Python 3:

>>> True = False
>>> True
False


回答11:

The better way is "while True" with a conditional break out of the loop.