2010-10-14 23 views
20

को छोड़कर मैं सोच रहा था कि नीचे दिए गए कार्यक्रम में प्रयास को छोड़कर धीमा क्यों है।पाइथन यदि बनाम कोशिश करें-

def tryway(): 
    try: 
     while True: 
      alist.pop() 
    except IndexError: 
     pass 

def ifway(): 
    while True: 
     if alist == []: 
      break 
     else: 
      alist.pop() 
if __name__=='__main__': 
    from timeit import Timer 
    alist = range(1000) 
    print "Testing Try" 
    tr = Timer("tryway()","from __main__ import tryway") 
    print tr.timeit() 
    print "Testing If" 
    ir = Timer("ifway()","from __main__ import ifway") 
    print ir.timeit() 

मुझे मिलने वाले परिणाम दिलचस्प हैं।

Testing Try 
2.91111302376 
Testing If 
0.30621099472 

क्या कोई भी कुछ प्रकाश डाल सकता है क्यों प्रयास इतना धीमा है?

+2

यह वास्तव में यहां लागू नहीं होता है, लेकिन कभी-कभी 'dis.dis (funcname)' को देखकर यह पता लगाने के लिए आसान होता है कि आंतरिक रूप से कुछ कैसे काम करता है – Daenyth

उत्तर

38

आप केवल एक बार सूची स्थापित कर रहे हैं। "ट्रावे" के लिए पहला कॉल इसे साफ़ करता है, फिर प्रत्येक लगातार कॉल कुछ भी नहीं करता है।

def tryway(): 
    alist = range(1000) 
    try: 
     while True: 
      alist.pop() 
    except IndexError: 
     pass 

def ifway(): 
    alist = range(1000) 
    while True: 
     if alist == []: 
      break 
     else: 
      alist.pop() 
if __name__=='__main__': 
    from timeit import Timer 
    print "Testing Try" 
    tr = Timer("tryway()","from __main__ import tryway") 
    print tr.timeit(10000) 
    print "Testing If" 
    ir = Timer("ifway()","from __main__ import ifway") 
    print ir.timeit(10000) 

>>> Testing Try 
>>> 2.09539294243 
>>> Testing If 
>>> 2.84440898895 
+4

धन्यवाद अब मैं बेवकूफ की तरह महसूस करता हूं: | – James

+42

जेम्स, अगर हमारे पास सीखने के लिए कुछ भी नहीं था और कभी मूर्खतापूर्ण गलतियों नहीं की गई थी, तो स्टैक ओवरव्लो के लिए कोई कारण नहीं होगा। – msw

0

यकीन नहीं है लेकिन मुझे लगता है कि यह ऐसा कुछ है: जबकि सत्य सामान्य निर्देश रेखा का पालन करें जिसका अर्थ है कि प्रोसेसर पाइपलाइन कर सकता है और अच्छी चीजों के सभी प्रकार कर सकता है। अपवाद सीधे उन सभी के माध्यम से कूदते हैं ताकि वीएम को इसे विशेष रूप से संभालने की आवश्यकता हो, और इसमें समय लगता है।

+0

जिस तरह से मैंने देखा, यह था कि अगर वह खुद को मार रहा है अपवाद यह केवल अंत में जांच रहा है और फिर समाप्त हो रहा है। जबकि अगर देखो 1000 बार सूची का परीक्षण कर रहा है जो मैंने सोचा था धीमा होगा .... – James

+0

मुझे लगता है कि खाली सूची के खिलाफ तुलना काफी तेज है, इसलिए यह बहुत समय नहीं कर पाती है। ध्यान दें, मुझे इन चीजों के बारे में निश्चित नहीं है, मैंने सोचा कि मैं आपको विचार की अपनी पंक्ति दूंगा। – dutt

4

अपवाद हैंडलिंग आमतौर पर अधिकांश भाषाओं में धीमी होती है। अधिकांश कंपाइलर, दुभाषिया और वीएम (जो अपवाद हैंडलिंग का समर्थन करते हैं) अपवादों (असामान्य) के रूप में अपवाद (भाषा मुहावरे) का इलाज करते हैं। प्रदर्शन अनुकूलन में व्यापार-बंद शामिल हैं और तेजी से अपवाद बनाना आम तौर पर भाषा के अन्य क्षेत्रों को भुगतना होगा (या तो डिजाइन के प्रदर्शन या सादगी में)।

अधिक तकनीकी स्तर पर, अपवादों का आम तौर पर अर्थ है कि वीएम/व्याख्याकर्ता (या रनटाइम निष्पादन लाइब्रेरी) को राज्य का एक समूह सहेजना है और फ़ंक्शन कॉल स्टैक (अनचाहे कहा जाता है) पर सभी राज्य को खींचना शुरू करना है वह बिंदु जहां वैध पकड़ (छोड़कर) पाई जाती है।

या इसे किसी भिन्न दृष्टिकोण से देखते हुए, प्रोग्राम अपवाद होने पर चल रहा है और "डीबगर" खत्म हो जाता है। यह डीबगर अपवाद से मेल खाने वाले कैच के लिए स्टैक (कॉलिंग फ़ंक्शन डेटा) के माध्यम से वापस खोजता है। यदि यह एक पाता है, तो यह चीजों को साफ करता है और उस बिंदु पर कार्यक्रम पर नियंत्रण देता है। यदि यह एक नहीं मिलता है तो यह उपयोगकर्ता को नियंत्रण देता है (शायद एक इंटरैक्टिव डीबगर या पायथन आरईपीएल के रूप में)।

+4

यह अजगर के संदर्भ में सुंदर विषय है। पायथन में अपवाद वास्तव में सस्ता हैं, और यदि असाधारण मामला अपवाद (जैसा होना चाहिए) से अधिक आम है, तो यह ग्लेन के उत्तर में सत्यापित किए गए चेक के रूप में चेक/कैच करने के लिए सस्ता होने जा रहा है। ईएएफपी> एलबीवाईएल। – Daenyth

3

यदि आप वास्तव में गति में रुचि रखते हैं, तो आपके दोनों प्रतियोगी कुछ वजन कम करने के साथ कर सकते हैं।

while True: से while 1: धीमी है - True एक वैश्विक "चर" जो भरा हुआ है और परीक्षण किया जाता है है; 1 एक स्थिर है और संकलक परीक्षण करता है और बिना शर्त कूदता है।

while True: ifway में अनावश्यक है। गुना, जबकि/अगर/एक साथ तोड़: while alist != []:

while alist != []: लेखन while alist:

प्रयास करें की एक धीमी तरीका है यह:

def tryway2(): 
    alist = range(1000) 
    try: 
     while 1: 
      alist.pop() 
    except IndexError: 
     pass 

def ifway2(): 
    alist = range(1000) 
    while alist: 
     alist.pop() 

`

+4

जबकि 'True' के बारे में आपकी टिप्पणी py 2.x के संदर्भ में सही है, py3k में यह एक वास्तविक कीवर्ड है और उस ओवरहेड नहीं है। – Daenyth

2

अभी भी तेज़ तरीका-बार दोहराना के लिए के साथ है, हालांकि कभी-कभी हम भौतिक रूप से शिरकत की सूची चाहते हैं ताकि हम जान सकें कि कितने बचाए गए हैं। फिर जनरेटर के लिए पैरामीटर होना चाहिए। (जॉन while alist: के लिए भी सही है) मैंने फ़ंक्शन को जेनरेटर और प्रयुक्त सूची (ifway()) आदि के रूप में रखा है।इसलिए मूल्यों वास्तव में समारोह से बाहर उपयोग किया जाता है (यहां तक ​​कि इस्तेमाल नहीं किया):

def tryway(): 
    alist = range(1000) 
    try: 
     while True: 
      yield alist.pop() 
    except IndexError: 
     pass 

def whileway(): 
    alist = range(1000) 
    while alist: 
     yield alist.pop() 

def forway(): 
    alist = range(1000) 
    for item in alist: 
     yield item 

if __name__=='__main__': 
    from timeit import Timer 
    print "Testing Try" 
    tr = Timer("list(tryway())","from __main__ import tryway") 
    print tr.timeit(10000) 
    print "Testing while" 
    ir = Timer("list(whileway())","from __main__ import whileway") 
    print ir.timeit(10000) 
    print "Testing for" 
    ir = Timer("list(forway())","from __main__ import forway") 
    print ir.timeit(10000) 

J:\test>speedtest4.py 
Testing Try 
6.52174983133 
Testing while 
5.08004508953 
Testing for 
2.14167694497 
+0

अपने परिणामों हालांकि बताते हैं कि 'try' एक छोटा सा' while' की तुलना में धीमी है, अजगर 3 के साथ अपने परीक्षण मुझे दिया है: 'जबकि 1.2370897208711098 परीक्षण के लिए 0.00439965737' (मैं सिर्फ जोड़ा परीक्षण 1.0719404926951281 परीक्षण की कोशिश करो प्रिंट स्टेटमेंट्स के लिए parantheses और 'रेंज (1000)' से 'सूची (रेंज (1000)) बदल दिया। 0) – AXO

-1

रक्षात्मक प्रोग्रामिंग की आवश्यकता है कि परिस्थितियों के दुर्लभ और/या असामान्य हैं, के लिए एक परीक्षण है जो एक वर्ष या कई वर्षों के दौरान के कुछ ऐसा नहीं होगा, इस प्रकार इन परिस्थितियों में शायद कोशिश-को छोड़कर उचित ठहराया जा सकता है।

+0

यह एक बहुत भ्रमित और अस्पष्ट जवाब है। कृपया स्पष्ट करें। – Difster

0

बस मिश्रण में इस टॉस करने के लिए सोचा: मेरा सुझाव है कि एक अपवाद के प्रबंधन में एक else बयान से निपटने की तुलना में धीमी लगता है, जो नीचे निम्न स्क्रिप्ट की कोशिश की:

import time 

n = 10000000 
l = range(0, n) 
t0 = time.time() 
for i in l: 
    try: 
     i[0] 
    except: 
     pass 
t1 = time.time() 
for i in l: 
    if type(i) == list(): 
     print(i) 
    else: 
     pass 
t2 = time.time() 
print(t1-t0) 
print(t2-t1) 

देता है:

5.5908801555633545 
3.512694835662842 

तो, (भले ही मुझे पता है कि की बजाय time के उपयोग पर टिप्पणी करने की संभावना है), ऐसा लगता है कि लूप में कोशिश/छोड़कर ~ 60% धीमा हो गया है। तो, कई अरब वस्तुओं के लूप के माध्यम से जाने पर शायद if/else के साथ जाना बेहतर होगा।

संबंधित मुद्दे