जबकि (1) बनाम जबकि (सच्चा) - अंतर क्यों है (अजगर 2 बाइटकोड में)?


115

पर्ल में अनंत छोरों के बारे में इस सवाल से प्रेरित: जबकि (1) बनाम। (;) के लिए गति में अंतर है? , मैंने अजगर में एक समान तुलना चलाने का फैसला किया। मुझे उम्मीद थी कि कंपाइलर के लिए समान बाइट कोड उत्पन्न होगा while(True): passऔर while(1): pass, लेकिन यह वास्तव में python2.7 में ऐसा नहीं है।

निम्नलिखित स्क्रिप्ट:

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)

निम्नलिखित परिणाम उत्पन्न करता है:

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        

का उपयोग करना while Trueअधिक जटिल है। ऐसा क्यों है?

अन्य संदर्भों में, अजगर True1 के बराबर काम करता है :

>>> True == 1
True

>>> True + True
2

whileदोनों में अंतर क्यों करता है ?

मैंने देखा कि python3 समान कार्यों का उपयोग करके कथनों का मूल्यांकन करता है:

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 में बूलियन के मूल्यांकन के तरीके में बदलाव होता है?


जवाबों:


124

पायथन 2.x में, Trueएक कीवर्ड नहीं है, लेकिन सिर्फ एक अंतर्निहित वैश्विक स्थिरांक है जिसे 1 boolप्रकार में परिभाषित किया गया है । इसलिए दुभाषिया को अभी भी सामग्री को लोड करना है True। दूसरे शब्दों में, Trueआश्वस्त है:

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

पायथन 3.x में यह वास्तव में एक कीवर्ड और वास्तविक स्थिरांक बन जाता है :

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

इस प्रकार दुभाषिया while True:लूप को अनंत लूप से बदल सकता है ।


1
@MH: AFAIK, यह भाषा में कीवर्ड प्राप्त करने के लिए एक समीचीन था।
— सल।

2
कुछ इतिहास के लिए docs.python.org/whatsnew/2.3.html#pep-285-a-boolean-type और python.org/dev/peps/pep-0285 देखें ।
— नेड डीली

क्या इसका मतलब while 1और while Trueपायथन 3 में समान हैं?
— स्टेवोइसेक

@ स्टीवनम.वस्केलारो यस।
— kennytm

14

यह काफी सही नहीं है,

इस प्रकार दुभाषिया जबकि सही को बदल सकता है: लूप एक अनंत लूप के साथ।

के रूप में एक अभी भी पाश से बाहर तोड़ सकते हैं। लेकिन यह सच है कि इस तरह के लूप का elseक्लाज पायथन 3 में कभी भी एक्सेस नहीं किया जाएगा। और यह भी सच है कि वैल्यू लुक को आसान बनाने से यह while 1पायथन 2 की तरह ही तेजी से चलता है ।

प्रदर्शन तुलना

लूप करते समय कुछ हद तक nontrivial के लिए समय में अंतर का प्रदर्शन:

सेट अप

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

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

अजगर २

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

अजगर ३

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

व्याख्या

अंतर समझाने के लिए, पायथन 2 में:

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

लेकिन पायथन 3 में:

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

चूंकि Trueपायथन 3 में एक कीवर्ड है, इसलिए दुभाषिया को यह देखने के लिए मूल्य नहीं देखना पड़ता है कि क्या किसी ने इसे किसी अन्य मूल्य के साथ बदल दिया है। लेकिन जब से कोई Trueदूसरे मूल्य पर असाइन कर सकता है , दुभाषिया को हर बार इसे देखना होगा।

पायथन 2 के लिए निष्कर्ष

यदि आपके पास पायथन 2 में एक तंग, लंबे समय तक चलने वाला लूप है, तो आपको संभवतः while 1:इसके बजाय का उपयोग करना चाहिए while True:।

पायथन 3 के लिए निष्कर्ष

उपयोग करें while True:यदि आपके पास अपने लूप को तोड़ने के लिए कोई शर्त नहीं है।


3

यह एक 7-वर्षीय प्रश्न है, जिसमें पहले से ही एक शानदार उत्तर है, लेकिन प्रश्न में गलत धारणा, जिसे किसी भी उत्तर में संबोधित नहीं किया गया है, यह डुप्लिकेट के रूप में चिह्नित कुछ अन्य प्रश्नों के लिए संभावित रूप से भ्रमित करता है।

अन्य संदर्भों में, अजगर सत्य के समान कार्य करता है:

>>> True == 1
True

>>> True + True
2

दोनों में अंतर क्यों करता है?

वास्तव में, whileयहाँ कुछ भी अलग नहीं किया जा रहा है। यह अलग 1और Trueबिल्कुल उसी तरह से है जैसे कि +उदाहरण करता है।


यहाँ 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

अब तुलना करें:

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

यह LOAD_GLOBAL (True)प्रत्येक के लिए उत्सर्जित कर रहा है True, और ऐसा कुछ भी नहीं है जो अनुकूलक वैश्विक के साथ कर सकता है। तो, whileभेद करता है 1और Trueठीक उसी कारण से जो +करता है। (और ==उन्हें भेद नहीं करता क्योंकि ऑप्टिमाइज़र तुलनाओं का अनुकूलन नहीं करता है।)


अब 3.6 की तुलना करें:

>>> 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

यहां, यह LOAD_CONST (True)कीवर्ड के लिए उत्सर्जित कर रहा है, जिसका आशावादी लाभ उठा सकते हैं। तो, बिल्कुल अलग True + 1 नहीं है, क्योंकि यही कारण while Trueनहीं है। (और ==अभी भी उन्हें भेद नहीं करता है क्योंकि ऑप्टिमाइज़र तुलनाओं का अनुकूलन नहीं करता है।)


इस बीच, यदि कोड को ऑप्टिमाइज़ नहीं किया गया है, तो दुभाषिया उपचार समाप्त कर देता है Trueऔर 1इन तीनों मामलों में बिल्कुल समान है। boolका एक उपवर्ग है int, और इसके अधिकांश तरीकों को विरासत में मिला है int, और Trueइसका आंतरिक पूर्णांक मूल्य है। 1. तो, चाहे आप एक whileपरीक्षण कर रहे हों ( __bool__3.x में, __nonzero__2.x में), एक तुलना ( __eq__), या अंकगणित। ( __add__), आप उसी विधि को कॉल कर रहे हैं चाहे आप उपयोग करें Trueया 1।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.