2010-03-29 34 views
9

एक दोस्त (साथी कम कौशल स्तर मनोरंजन पायथन स्क्रिप्टर) ने मुझे कुछ कोड देखने के लिए कहा। मैंने देखा कि उसके पास 7 अलग-अलग वक्तव्य थे जो मूल रूप से कहा गया था।पायथन अगर कथन दक्षता

if (a and b and c): 
    do something 

बयान ए, बी, सी सभी ने उनकी समानता या मूल्य निर्धारित करने की कमी का परीक्षण किया। जैसा कि मैंने देखा, मैंने पाया कि परीक्षणों की प्रकृति के कारण, मैं पूरे तर्क ब्लॉक को दो शाखाओं में फिर से लिख सकता हूं जो कभी भी 3 से अधिक गहरे नहीं गए और शायद ही कभी पहले स्तर से पहले (सबसे दुर्लभ घटना परीक्षण प्रथम)।

if a: 
    if b: 
     if c: 
    else: 
     if c: 
else: 
    if b: 
     if c: 
    else: 
     if c: 

मेरे लिए, तार्किक रूप से ऐसा लगता है जैसे कि यह तेजी से होना चाहिए, अगर आप कम, सरल परीक्षण है कि तेजी से असफल और आगे बढ़ने कर रहे हैं। मेरे असली प्रश्न

1) जब मैं कहता हूं कि और क्या, यदि सत्य हो, तो क्या यह पूरी तरह से अनदेखा हो जाता है?

2) सिद्धांत रूप में होगा

अगर (ए और बी और के रूप में तीन अलग-अलग ग)

लेने के रूप में ज्यादा समय अगर बयान करेंगे?

उत्तर

27

if कथन else ब्रैकेट में सबकुछ छोड़ देगा यदि यह सत्य का मूल्यांकन करता है। यह ध्यान दिया जाना चाहिए कि इस तरह की समस्या के बारे में चिंता करते हुए, जब तक कि यह कार्यक्रम निष्पादन के लाखों बार नहीं किया जाता है, को "समयपूर्व अनुकूलन" कहा जाता है और इससे बचा जाना चाहिए। यदि आपका कोड तीन if (a and b and c) कथन के साथ स्पष्ट है, तो उन्हें

+11

सहमत हुए। प्रदर्शन के बारे में चिंता न करें, पठनीयता के बारे में चिंता करें। मार्टिन फाउलर की तरह कहते हैं: "कोई भी मूर्ख कोड लिख सकता है जो एक कंप्यूटर समझ सकता है ... लेकिन केवल अच्छे प्रोग्रामर कोड लिखते हैं जो मनुष्य समझ सकते हैं।" –

+2

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

1

if (a and b and c)a गलत साबित होगा, और b या c की जांच करने से परेशान नहीं होगा।

उसने कहा, मुझे व्यक्तिगत रूप से लगता है कि घोंसले की सशर्त सशर्त के 2^एन संयोजनों से पढ़ने के लिए आसान है।

सामान्य रूप से, यदि आप यह निर्धारित करना चाहते हैं कि कुछ करने का तरीका सबसे तेज़ है, तो आप timeit का उपयोग करके एक साधारण बेंचमार्क लिख सकते हैं।

3

मुझे संदेह है कि आपको एक मापनीय अंतर दिखाई देगा, इसलिए मैं कोड को सबसे अधिक पढ़ने योग्य बनाने की अनुशंसा करता हूं।

8

कम से कम पायथन में, दक्षता पठनीयता के लिए दूसरी है और "फ्लैट नेस्टेड से बेहतर है"।

The Zen of Python

29

मैं कहूंगा कि एक परीक्षण के रूप में तेजी से अलग परीक्षण के रूप में है देखें। पायथन भी short-circuit evaluation का उपयोग करता है।

(a and b and c) के लिए इसका मतलब है, कि b या c अब और परीक्षण नहीं किया जाएगा अगर afalse है।

इसी प्रकार, यदि आप एक OR अभिव्यक्ति (a or b) और atrue है, b का मूल्यांकन कभी नहीं किया गया है।

तो समेकित करने के लिए, खंड अलग होने के साथ तेजी से विफल नहीं होते हैं।

+0

ग्रेट अतिरिक्त बिंदु, धन्यवाद। – Dennis

16

कोड:

import dis 

def foo(): 
    if (a and b and c): 
    pass 
    else: 
    pass 

def bar(): 
    if a: 
    if b: 
     if c: 
     pass 

print 'foo():' 
dis.dis(foo) 
print 'bar():' 
dis.dis(bar) 

आउटपुट:

foo(): 
    4   0 LOAD_GLOBAL    0 (a) 
       3 JUMP_IF_FALSE   18 (to 24) 
       6 POP_TOP    
       7 LOAD_GLOBAL    1 (b) 
      10 JUMP_IF_FALSE   11 (to 24) 
      13 POP_TOP    
      14 LOAD_GLOBAL    2 (c) 
      17 JUMP_IF_FALSE   4 (to 24) 
      20 POP_TOP    

    5   21 JUMP_FORWARD    1 (to 25) 
     >> 24 POP_TOP    

    7  >> 25 LOAD_CONST    0 (None) 
      28 RETURN_VALUE   
bar(): 
10   0 LOAD_GLOBAL    0 (a) 
       3 JUMP_IF_FALSE   26 (to 32) 
       6 POP_TOP    

11   7 LOAD_GLOBAL    1 (b) 
      10 JUMP_IF_FALSE   15 (to 28) 
      13 POP_TOP    

12   14 LOAD_GLOBAL    2 (c) 
      17 JUMP_IF_FALSE   4 (to 24) 
      20 POP_TOP    

13   21 JUMP_ABSOLUTE   29 
     >> 24 POP_TOP    
      25 JUMP_ABSOLUTE   33 
     >> 28 POP_TOP    
     >> 29 JUMP_FORWARD    1 (to 33) 
     >> 32 POP_TOP    
     >> 33 LOAD_CONST    0 (None) 
      36 RETURN_VALUE   

इसलिए, भले ही सेटअप में ही है, संयुक्त अभिव्यक्ति के लिए सफाई तेजी के बाद से यह ढेर पर केवल एक ही मूल्य छोड़ देता है।

3

आप ख या ग जा रहा कार्यों कि बस चर कि मूल्यांकन किया जाता है के बजाय कहा जाता है के बारे में चिंतित हैं, तो इस कोड को पता चलता है कि कम-सर्किटिंग अपने दोस्त है:

a = False 
def b(): 
    print "b was called" 
    return True 

if a and b(): 
    print "this shouldn't happen" 
else: 
    print "if b was not called, then short-circuiting works" 

प्रिंट

if b was not called, then short-circuiting works 

लेकिन यह करता है कि यदि आप कोड है:

a = call_to_expensive_function_A() 
b = call_to_expensive_function_B() 
c = call_to_expensive_function_C() 

if a and b and c: 
    do something... 

फिर अपना कोड stil है मैं सभी 3 महंगे कार्यों को बुला रहा हूँ। बेहतर अजगर अजगर हो जाने के लिए:

if (call_to_expensive_function_A() and 
    call_to_expensive_function_B() and 
    call_to_expensive_function_C()) 
    do something... 

जो केवल आवश्यक के रूप में कई महंगा कार्यों कॉल करेंगे समग्र हालत निर्धारित करने के लिए।

# note, this is a list of the functions themselves 
# the functions are *not* called when creating this list 
funcs = [function_A, function_B, function_C] 

if all(fn() for fn in funcs): 
    do something 

अब आप अन्य कार्यों जोड़ सकते हैं या उन्हें पुन: व्यवस्थित करना चाहते हैं के लिए है, तो (शायद function_A बहुत समय है:

संपादित

आप इस का उपयोग कर all निर्मित सामान्यीकरण कर सकते हैं उपभोग करने वाले, और आपको function_B या function_C पहले विफल होने वाले मामलों को फ़िल्टर करके लाभ होगा), आप बस funcs सूची अपडेट करें। all शॉर्ट सर्किटिंग करता है जैसे कि आपने if a and b and c के रूप में लिखा था। (यदि फ़ंक्शन 'या' एक साथ हैं, तो any इसके बजाय बिल्टिन का उपयोग करें।)

0

if (a and b and c) "वास्तविक प्रोग्रामर कोड अनुकूलन" और कोड पठनीयता के लिए तेज़ और बेहतर है।

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