सवाल अगर या तो सच है तो कुछ करो


यह सिर्फ अकादमिक हित के लिए है। मुझे निम्नलिखित स्थिति का सामना करना पड़ता है।

either_true = False
if x:
  ...do something1
  either_true = True
elif y:
  ...do something2
  either_true = True
if either_true:
  ..do something3

क्या ऐसा करने का कोई पाइथोनिक तरीका है, या इसे करने के सामान्य प्रोग्रामिंग तरीके में। मूल रूप से कुछ 3 निष्पादित करते हैं यदि elif सत्य है या नहीं।


44
2018-02-13 14:04


मूल


ऐसा लगता है कि आपका वर्तमान समाधान इष्टतम है। ChrisProsser के उत्तर जैसे अन्य दृष्टिकोण, मूल्यांकन की आवश्यकता है x और / या y एक से ज्यादा बार। - Frédéric Hamidi
किसी फ़ंक्शन में कुछ 3 रखें, और इसे दोनों शाखाओं से कॉल करें। - RemcoGerlich
यह एक प्रमुख मामला होगा if...else...finally, बहुत बुरा है कि अस्तित्व में नहीं है। - wnnmaw
@wnnmaw - मैं असहमत हूं। मुझे अपेक्षा होगी finally किसी भी मामले को निष्पादित करने के लिए - क्या नहीं, केवल खंडों में से एक सत्य था-इश। - mgilson
मेरे पास इस तरह का कोड था, लेकिन if..elif और if के बीच सामान था, इस मामले में मुझे वास्तव में लगता है कि यह सबसे अच्छा समाधान है - Cruncher


जवाब:


आपका कोड है लगभग इष्टतम, जहां तक ​​कोड पुनरावृत्ति और मूल्यांकन का संबंध है। पुनरावृत्ति से बचने के लिए मैं केवल एक चीज सोच सकता हूं:

# be optimistic!
either_true = True
if x:
    do_something1
elif y:
    do_something2
else:
    either_true = False

if either_true:
    do_something3

यह एक असाइनमेंट को हटा देता है, हालांकि लाइनों की कुल संख्या में बदलाव नहीं होता है।

इसका फायदा यह है कि यह काम करता है n शर्तों, बिना किसी अन्य असाइनमेंट को जोड़ने के, जबकि आपके वर्तमान समाधान की आवश्यकता है either_true = True हर शर्त के लिए।

मेरी राय में उनके पास पठनीयता की एक ही डिग्री है, लेकिन उपरोक्त कोड अधिक स्थितियों के साथ बेहतर होगा।

इसके अलावा कोई भी "पायथनिक" तरीका नहीं है, फिर एक पठनीय समाधान जो कोड पुनरावृत्ति से बचाता है और दक्षता के मामले में इष्टतम है, और मुझे एक ही परिणाम प्राप्त करने के लिए किसी भी प्रकार के "बेहतर प्रोग्रामिंग" के बारे में पता नहीं है।


31
2018-02-13 20:14



यह निश्चित रूप से अवधारणा को बुद्धिमानी में सुधारता है - user1572215
यह स्पष्ट रूप से सबसे अच्छा जवाब है। - KRyan
यह विशिष्ट प्रश्न के लिए एक अच्छा जवाब है, लेकिन यदि कोई अन्य 'एलिफ' था जहां या तो गलत होना चाहिए, तो यह बहुत फायदेमंद नहीं होगा। मूल प्रश्न 'अकादमिक हित' था, इसलिए यह संभावना नहीं है कि यह केवल एक एलिफ स्टेटमेंट तक ही सीमित हो। - Alex
@ एलेक्स असल में आप बस डाल सकते हैं either_true=False प्रत्येक शाखा पर जहां यह होना चाहिए False। शाखाओं की संख्या के आधार पर आप उपयोग करने के लिए चुन सकते हैं True या False असाइनमेंट की संख्या को कम करने के लिए डिफ़ॉल्ट के रूप में। जैसा कि मैंने स्पष्ट रूप से मेरे उत्तर में कहा है, अगर हम आपके मामले में सामान्यीकृत करते हैं n परिस्थितियों और आप वैरिएबल को सच होना चाहते हैं कोई उनमें से सत्य है, तो मेरे उत्तर में कोड इष्टतम समाधान है। इसके अलावा मैं नहीं देखता कि अन्य उत्तरों इसे कैसे ध्यान में रखते हैं। - Bakuriu
इसका नकारात्मक पक्ष यह है कि संबंधित कोड (उदा। do_something1 के बाद do_something3) लाइनों के दर्जनों अलग हो सकते हैं, कोड पढ़ने के दौरान आपको नीचे कूदना होगा। सब सिर्फ इसलिए कि आप दोहराना नहीं चाहते हैं do_something3 - और इसे दोहराने से बचने के लिए इतनी मेहनत करने का कारण निश्चित रूप से है क्योंकि यह एक एकल फ़ंक्शन कॉल से अधिक है। राज्य का एक टुकड़ा जोड़ना (द either_true) चर उस समस्या के समाधान के समान लगता है do_something3 इसे दोहराने के लिए बहुत अधिक कोड है जहां यह होना चाहिए (ठीक नीचे do_something1उदाहरण के लिए) व्यवहार्य। - Frerich Raabe


आप भी छोड़ सकते हैं either_true पूरी तरह झंडा अगर doSomething3 कोड की एक पंक्ति है (उदा। एक फ़ंक्शन कॉल):

if x:
  ..do something 1
  ..do something 3
elif y:
  ..do something 2
  ..do something 3

यह मूल्यांकन की अच्छी संपत्ति को बनाए रखता है x तथा y ज्यादातर बार (और y अगर मूल्यांकन नहीं किया जाएगा x सच हैं)।


35
2018-02-13 14:12



महान। कोड की 1 पंक्ति दोहराने के लिए ठीक है ... - glglgl
अगर do something 3 एक समारोह कॉल है, तो हाँ, यह बहुत अच्छा है। मैं इसे बुलियन दृष्टिकोण पर ले जाऊंगा। - 2rs2ts
और यदि यह फ़ंक्शन कॉल नहीं है, तो शायद इसे एक में बदल दिया जा सकता है। - RemcoGerlich
@ZanLynx बूलियन के साथ उन्हें सेट करना याद रखना होगा either_true = True, और घोंसले के साथ अगर बयान उन्हें जोड़ना याद रखना है z दो स्थानों पर यह अनिवार्य है कि किसी तीसरे (या अधिक) मामलों को जोड़ने पर कहीं भी जोड़ा जाना चाहिए, लेकिन यह आईएमओ सबसे अधिक रखरखाव योग्य है। - Izkata
@ thedayturns मुझे लगता है कि पर्याप्त स्पष्ट नहीं था: आईएमएचओ सबसे अच्छा तय है जो भी कोड को स्थानांतरित करना है doSomething3 एक अलग समारोह में खड़ा है। यह (जैसा कि @ user1572215 सही ढंग से इंगित किया गया है) भी सवाल को अप्रचलित करता है। - Frerich Raabe


अगर मैं कथन का उपयोग कर घोंसला का उपयोग कर इसे संभालता हूं i.e.

if x or y:
    if x:
        ...do something1
    elif y:
        ...do something2
    ...do something3

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


19
2018-02-13 14:07



mmm ... अगर x तथा y सरल अभिव्यक्तियां हैं, फिर हां। अन्यथा, नहीं। - glglgl
@ क्रिस्टियन यदि वे सरल अभिव्यक्ति नहीं हैं, ई। जी। एक फ़ंक्शन कॉल शामिल करें, कॉल दो बार किया जाता है, जो वांछित चीज़ नहीं हो सकता है। - glglgl
@Christian, x हो सकता है compare_thousands_of_matrices() तथा y हो सकता है check_slow_server_response(), उदाहरण के लिए। - Frédéric Hamidi
आप वेरिएबल को परिणाम (फ़ंक्शन द्वारा लौटाए गए मान) को असाइन कर सकते हैं x तथा y, इसलिए शामिल किसी भी समारोह में केवल एक बार मूल्यांकन किया जाता है। - Christian
इस मामले में "elif y:" को "else:" द्वारा प्रतिस्थापित किया जा सकता है - Kundor


आप इसे कुछ फ़ंक्शन में लपेट सकते हैं:

def do_stuff():
    if x:
        ...do something1
        return True
    elif y:
        ...do something2
        return True
    else:
        return False

if do_stuff():
    ..do something3

या यह सब एक समारोह में:

def do_stuff()
    if x:
        ...do something1
    elif y:
        ...do something2
    else:
        return

    ..do something3

7
2018-02-13 14:11



आप भी सुझाव दे सकते हैं इस तरह, मेरे हटाए गए उत्तर को देखें। - Grijesh Chauhan
@GrijeshChauhan: हालांकि उस मामले में वापसी मूल्य के अर्थ को औचित्य साबित करना मुश्किल हो जाता है - Eric
हाँ तो मैंने एक मिनट के भीतर अपना जवाब हटा दिया। यह पहले भ्रमित है और कुछ प्रोग्रामर इसे योड-नोटेशन की तरह नापसंद करेंगे। लेकिन फिर भी मैं साझा करना चाहता था इसलिए मैंने टिप्पणी की। - Grijesh Chauhan


पहले से प्रस्तावित लोगों के लिए एक पूरी तरह से अलग समाधान की पेशकश की भावना में, आप एक सूची संरचित शब्दकोश स्थापित कर सकते हैं जो आपको अपने पूर्वनिर्धारित "somethings" से जुड़े कई मामलों को स्थापित करने की अनुमति देता है

cases = [
    {'condition' : x, 'action' : something1},
    {'condition' : not x and y, 'action' : something2},
    {'condition' : x or y, 'action' : something3},
]

for c in cases:
    if c['condition']: c['action']

मुझे वास्तव में वास्तव में इस विधि को पसंद है (और मैंने केवल इस प्रश्न के अनूठे उत्तर के साथ आने का प्रयास करते समय इसे खोज लिया है, धन्यवाद!) - यह वास्तव में स्पष्ट है कि कौन सा मामला किस कार्रवाई से जुड़ा हुआ है, और कई और जोड़ना आसान है अगर / और कथन के बिना और अधिक जोड़ने के मामले।


6
2018-02-13 17:45



ChrisProsser के उत्तर के समान ही समस्या - यह काम करता है x तथा y सरल हैं, लेकिन यदि वे वास्तव में महंगे फ़ंक्शन कॉल हैं तो आपको उन्हें पहले चर में निकालना होगा, इसलिए उन्हें कई बार नहीं कहा जाता है। और फिर भी, सब उन सशर्तों को चलाने के लिए जा रहे हैं, जो आप शायद नहीं चाहते हैं। - Izkata
उत्कृष्ट योग्यता Izkata! - Quentin Donnellan
यदि आप मेक का उपयोग करते हैं cases शर्तों के लिए टुपल्स बंडलिंग (लैम्ब्डा) कार्यों की एक सादा सूची और मेल खाने वाले कोड को लागू करने वाले कार्यों के लिए, आप वास्तविक लूप को केवल लागू कर सकते हैं results = [action() for (condition, action) in cases if condition(x,y)]। डेटा को डेटा में बदलने के लिए इस दृष्टिकोण का एक अच्छा पहलू यह है कि आप आसानी से मामलों की संख्या गिनने या पंजीकृत स्थितियों या इसी तरह की गणना करने जैसी चीजें कर सकते हैं। यह कमांड दुभाषियों के लिए अच्छा काम करता है (आईआरसी क्लाइंट्स को सोचें जिन्हें कस्टम कमांड के साथ बढ़ाया जा सकता है)। - Frerich Raabe


if x or y:
    dosomethig1() if x else dosomething2()
    dosomething3()

बेशक, यह मूल्यांकन करता है x.__nonzero__ दो बार। आम तौर पर यह एक बड़ा सौदा नहीं है, लेकिन यदि यह महंगा है, तो आप हमेशा उस अग्रिम का मूल्यांकन कर सकते हैं और इसे अस्थायी चर में सहेज सकते हैं।


5
2018-02-13 14:08



अगर x and y, dosomething2() यूर समाधान के साथ छोड़ दिया गया है। - glglgl
अगर मैं ... और संरचना से असहमत हूं। एक्स का मतलब वाई नहीं है। - Theox
@glglgl - हाँ, मुझे पता है। यह ओपी में भी छोड़ दिया गया है। - mgilson
@Theox - इस मामले में, हाँ ऐसा इसलिए करता है क्योंकि यह इसमें है if x or y खंड। उनमें से एक सच होना चाहिए (आईएसएच)। यदि यह नहीं है x, फिर इसके y - mgilson
@mgilson ओच, ठीक है। मैंने छोड़ दिया elif: अंश... - glglgl


इन सभी सुझावों और किसी भी अन्य के साथ आने के लिए, ध्यान दें कि अगर x तथा y महंगी अभिव्यक्तियां हैं:

if askTheServer() or readTheOneGigabyteConfigFile():
   ...

आप मूल्यों को आवंटित कर सकते हैं ये अभिव्यक्ति पहले चर-बारी-मूल्यांकन चर पर वापस आती हैं:

x = askTheServer()
y = readTheOneGigabyteConfigFile()
if x or y :
   ...

4
2018-02-14 00:37





either_true = x or y
if x:
  ...do something1
elif y:
  ...do something2
if either_true:
  ..do something3

2
2018-02-13 14:14



दोनों x or y तथा any([x, y]) गैर-बूलियन के साथ भी इसका मतलब है। - glglgl
ओह, तुम सही हो। मैं उस टिप्पणी से छुटकारा पा लिया। - Jae


मैं कामों में कुछ भी लपेटूंगा और एक-एलीफ लिखूंगा:

def do_x():
  .. do something 1
  .. do something 3

def do_y():
  .. do something 2
  .. do something 3

if x:
   do_x()
elif y:
   do_y()

यह अच्छा है अगर .. कुछ चीजों में बहुत सारी चीजें शामिल हैं।


2
2018-02-13 23:17





अगर कुछ करना बहुत छोटा है, जैसे (1), ऐसा करें (2) या ऐसा कुछ, आप इसे इस तरह कर सकते हैं:

(x and (do(1), x) or y and (do(2), y)) and do(3)

0
2018-02-21 06:57