while (1) vs. while (Doğru) - Neden bir fark var (python 2 bayt kodunda)?


115

Perl'deki sonsuz döngülerle ilgili bu soru ilgisini çekti: while (1) Vs. for (;;) Hız farkı var mı? , Python'da benzer bir karşılaştırma yapmaya karar verdim. Ben derleyici için aynı bayt kodu oluşturmak bekleniyordu while(True): passve while(1): passfakat bu aslında python2.7 içinde durum böyle değildir.

Aşağıdaki komut dosyası:

import dis

def while_one():
    while 1:
        pass

def while_true():
    while True:
        pass

print("while 1")
print("----------------------------")
dis.dis(while_one)

print("while True")
print("----------------------------")
dis.dis(while_true)

aşağıdaki sonuçları verir:

while 1
----------------------------
  4           0 SETUP_LOOP               3 (to 6)

  5     >>    3 JUMP_ABSOLUTE            3
        >>    6 LOAD_CONST               0 (None)
              9 RETURN_VALUE        
while True
----------------------------
  8           0 SETUP_LOOP              12 (to 15)
        >>    3 LOAD_GLOBAL              0 (True)
              6 JUMP_IF_FALSE            4 (to 13)
              9 POP_TOP             

  9          10 JUMP_ABSOLUTE            3
        >>   13 POP_TOP             
             14 POP_BLOCK           
        >>   15 LOAD_CONST               0 (None)
             18 RETURN_VALUE        

kullanma while True belirgin şekilde daha karmaşıktır. Bu neden?

Diğer bağlamlarda, python True1'e eşitmiş gibi davranır :

>>> True == 1
True

>>> True + True
2

Neden yapar while ikisini birbirinden ayırıyor?

Python3'ün ifadeleri aynı işlemleri kullanarak değerlendirdiğini fark ettim:

while 1
----------------------------
  4           0 SETUP_LOOP               3 (to 6) 

  5     >>    3 JUMP_ABSOLUTE            3 
        >>    6 LOAD_CONST               0 (None) 
              9 RETURN_VALUE         
while True
----------------------------
  8           0 SETUP_LOOP               3 (to 6) 

  9     >>    3 JUMP_ABSOLUTE            3 
        >>    6 LOAD_CONST               0 (None) 
              9 RETURN_VALUE         

Python3'te booleanların değerlendirilme biçiminde bir değişiklik var mı?


Yanıtlar:


124

Python 2.x'te, Truebir anahtar kelime değil, yalnızca tipte 1 olarak tanımlanan yerleşik bir global sabittirbool . Bu nedenle, tercümanın hala içeriğini yüklemesi gerekir True. Başka bir deyişle, Trueyeniden atanabilir:

Python 2.7 (r27:82508, Jul  3 2010, 21:12:11) 
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> True = 4
>>> True
4

Python 3.x'te bu gerçekten bir anahtar kelime ve gerçek bir sabit olur:

Python 3.1.2 (r312:79147, Jul 19 2010, 21:03:37) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> True = 4
  File "<stdin>", line 1
SyntaxError: assignment to keyword

dolayısıyla yorumlayıcı while True:döngüyü sonsuz bir döngü ile değiştirebilir .


1
@MH: AFAIK, anahtar kelimeyi dile getirmek uygun oldu.
S.Lott


Bu Python 3'te aynı mı while 1ve while Trueaynı mı?
Stevoisiak

@ StevenM.Vascellaro Evet.
kennytm

14

Bu tam olarak doğru değil

böylece yorumlayıcı while True: döngüsünü sonsuz bir döngü ile değiştirebilir.

hala döngüden çıkabileceğinden. Ancak, böyle bir döngünün elseyan tümcesine Python 3'te asla erişilemeyeceği doğrudur. Ayrıca değer aramasını basitleştirmenin, onu aynı hızda çalıştırdığıwhile 1 Python 2'deki .

Performans karşılaştırması

Biraz önemsiz bir while döngüsü için zamandaki farkın gösterilmesi:

Kurmak

def while1():
    x = 0
    while 1:
        x += 1
        if x == 10:
            break

def whileTrue():
    x = 0
    while True:
        x += 1
        if x == 10:
            break

Python 2

>>> import timeit
>>> min(timeit.repeat(while1))
0.49712109565734863
>>> min(timeit.repeat(whileTrue))
0.756627082824707

Python 3

>>> import timeit
>>> min(timeit.repeat(while1))
0.6462970309949014
>>> min(timeit.repeat(whileTrue))
0.6450748789939098

açıklama

Python 2'deki farkı açıklamak için:

>>> import keyword
>>> 'True' in keyword.kwlist
False

ancak Python 3'te:

>>> import keyword
>>> 'True' in keyword.kwlist
True
>>> True = 'true?'
  File "<stdin>", line 1
SyntaxError: can't assign to keyword

Yana TruePython 3'te bir anahtar kelimedir, tercüman birisi başka bir değer ile değiştirdiğini görmek için değer bakmak zorunda değildir. Ancak biri Truebaşka bir değere atayabildiği için, tercümanın her seferinde ona bakması gerekir.

Python 2 için Sonuç

Python 2'de sıkı, uzun süren bir döngünüz varsa, while 1:bunun yerine muhtemelen kullanmalısınız while True:.

Python 3 için Sonuç

Döngünüzü while True:kırmak için bir koşulunuz yoksa kullanın .


3

Bu, zaten harika bir cevabı olan 7 yıllık bir sorudur, ancak yanıtların hiçbirinde ele alınmayan sorudaki bir yanlış anlama, yinelenen olarak işaretlenen diğer bazı sorular için potansiyel olarak kafa karıştırıcı hale getirir.

Diğer bağlamlarda python, True eşittir 1 gibi davranır:

>>> True == 1
True

>>> True + True
2

While neden ikisini birbirinden ayırıyor?

Aslında whileburada hiç farklı bir şey yapmıyor. Ayırdediyor 1ve Truetıpkı +örnekle aynı şekilde .


İşte 2.7:

>>> dis.dis('True == 1')
  1           0 LOAD_GLOBAL              0 (True)
              3 LOAD_CONST               1 (1)
              6 COMPARE_OP               2 (==)
              9 RETURN_VALUE

>>> dis.dis('True == 1')
  1           0 LOAD_GLOBAL              0 (True)
              3 LOAD_GLOBAL              0 (True)
              6 BINARY_ADD
              9 RETURN_VALUE

Şimdi karşılaştırın:

>>> dis.dis('1 + 1')
  1           0 LOAD_CONST               1 (2)
              3 RETURN_VALUE

Her LOAD_GLOBAL (True)biri için bir yayınlıyor Trueve optimize edicinin global ile yapabileceği hiçbir şey yok. Öyleyse, whileayırt eder 1ve Truebununla aynı nedenden dolayı +. (Ve ==optimize edici karşılaştırmaları optimize etmediği için bunları ayırt etmez.)


Şimdi 3.6 ile karşılaştırın:

>>> dis.dis('True == 1')
  1           0 LOAD_CONST               0 (True)
              2 LOAD_CONST               1 (1)
              4 COMPARE_OP               2 (==)
              6 RETURN_VALUE

>>> dis.dis('True + True')
  1           0 LOAD_CONST               1 (2)
              2 RETURN_VALUE

Burada, bir yaydığı LOAD_CONST (True)iyileştirici anahtar kelime için olabilir yararlanmak. Yani, True + 1 değil aynı nedenle, ayırt while Trueetmez. (Ve ==yine de onları ayırt etmiyor çünkü optimize edici karşılaştırmaları optimize etmiyor.)


Kod dışarı optimize değilse arada, tercüman tedavi biter Trueve 1bu durumlarda üçünde de tam olarak aynı. boolbir alt sınıfıdır intve yöntemlerinin çoğundan miras alır intve True1 dahili tamsayı değerine sahiptir. Yani, ister bir whiletest ( __bool__3.x'te, __nonzero__2.x'te), bir karşılaştırma ( __eq__) veya aritmetik yapıyor olun ( __add__), Trueveya kullanıyor olsanız da aynı yöntemi çağırıyorsunuz 1.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.