व्यवहार में, पायथन 3.3 में सिंटैक्स से नए "उपज" के लिए मुख्य उपयोग क्या हैं?


407

मुझे पीईपी 380 के आसपास अपने मस्तिष्क को लपेटने में मुश्किल समय हो रहा है ।

  1. ऐसी कौन सी परिस्थितियाँ हैं जहाँ "से उपज" उपयोगी है?
  2. क्लासिक उपयोग मामला क्या है?
  3. इसकी तुलना सूक्ष्म धागों से क्यों की जाती है?

[ अपडेट करें ]

अब मैं अपनी कठिनाइयों का कारण समझता हूं। मैंने जनरेटर का उपयोग किया है, लेकिन वास्तव में कभी भी कोरटाइन ( पीईपी -342 द्वारा पेश ) का उपयोग नहीं किया है । कुछ समानताओं के बावजूद, जनरेटर और कोरटाइन मूल रूप से दो अलग अवधारणाएं हैं। कोरटाइन को समझना (न केवल जनरेटर) नए वाक्यविन्यास को समझने की कुंजी है।

IMHO कोरआउट सबसे अस्पष्ट पायथन सुविधा है , अधिकांश पुस्तकें इसे बेकार और अविरल दिखाती हैं।

महान जवाब के लिए धन्यवाद, लेकिन agf और डेविड बेज़ले प्रस्तुतियों से जोड़ने वाली उनकी टिप्पणी के लिए विशेष धन्यवाद । डेविड चट्टानों।



7
डेविड बेज़ले की दबीज़.कॉम की वीडियो प्रस्तुति: youtube.com/watch?v=Z_OAlIhXziw
jcugat

जवाबों:


570

चलिए पहले एक बात समझ लेते हैं। जो व्याख्या yield from gसमतुल्य है, for v in g: yield v वह भी न्याय करने के लिए शुरू नहीं होती है जो yield fromसब के बारे में है। क्योंकि, चलो इसका सामना करते हैं, यदि सभी लूप yield fromका विस्तार करते हैं for, तो यह yield fromभाषा को जोड़ने का वारंट नहीं करता है और पायथन 2.x में कार्यान्वित होने से नई सुविधाओं का एक पूरा गुच्छा तैयार करता है।

यह क्या yield fromकरता है यह कॉलर और उप-जनरेटर के बीच एक पारदर्शी द्विदिश कनेक्शन स्थापित करता है :

  • कनेक्शन "पारदर्शी" इस अर्थ में है कि यह सब कुछ सही ढंग से भी प्रचारित करेगा, न कि केवल उत्पन्न होने वाले तत्व (जैसे अपवाद प्रचारित हैं)।

  • कनेक्शन "द्विदिश" अर्थ में डेटा दोनों भेजा जा सकता है वह यह है कि से और करने के लिए एक जनरेटर।

( यदि हम टीसीपी के बारे में बात कर रहे थे, तो yield from gइसका मतलब हो सकता है "अब मेरे ग्राहक के सॉकेट को अस्थायी रूप से डिस्कनेक्ट करें और इसे अन्य सर्वर सॉकेट से फिर से कनेक्ट करें"। )

BTW, यदि आप सुनिश्चित नहीं हैं कि किसी जेनरेटर को डेटा भेजने का क्या मतलब है, तो आपको सबकुछ छोड़ना होगा और पहले कॉरटुइन के बारे में पढ़ना होगा - वे बहुत उपयोगी हैं ( सबरूटीन के विपरीत ), लेकिन दुर्भाग्य से पायथन में कम जाना जाता है। डेव बेज़ले का कूर्टिंस पर क्यूरियस कोर्स एक उत्कृष्ट शुरुआत है। त्वरित प्राइमर के लिए स्लाइड 24-33 पढ़ें

से उपज का उपयोग कर एक जनरेटर से डेटा पढ़ना

def reader():
    """A generator that fakes a read from a file, socket, etc."""
    for i in range(4):
        yield '<< %s' % i

def reader_wrapper(g):
    # Manually iterate over data produced by reader
    for v in g:
        yield v

wrap = reader_wrapper(reader())
for i in wrap:
    print(i)

# Result
<< 0
<< 1
<< 2
<< 3

इसके बजाय मैन्युअल रूप से पुनरावृत्ति करने के बजाय reader(), हम yield fromइसे कर सकते हैं।

def reader_wrapper(g):
    yield from g

यह काम करता है, और हमने कोड की एक पंक्ति को समाप्त कर दिया। और शायद आशय थोड़ा स्पष्ट है (या नहीं)। लेकिन कुछ भी नहीं जीवन बदल रहा है।

1 से उपज का उपयोग करके एक जनरेटर (कोरटाइन) को डेटा भेजना

अब कुछ और दिलचस्प करते हैं। आइए एक कॉरआउट बनाते हैं, जो writerइसे भेजे गए डेटा को स्वीकार करता है और सॉकेट, एफडी आदि को लिखता है।

def writer():
    """A coroutine that writes data *sent* to it to fd, socket, etc."""
    while True:
        w = (yield)
        print('>> ', w)

अब सवाल यह है कि रैपर फ़ंक्शन को लेखक को डेटा भेजने से कैसे निपटना चाहिए, ताकि रैपर को भेजे जाने वाले किसी भी डेटा को पारदर्शी रूप से भेजा जाए writer()?

def writer_wrapper(coro):
    # TBD
    pass

w = writer()
wrap = writer_wrapper(w)
wrap.send(None)  # "prime" the coroutine
for i in range(4):
    wrap.send(i)

# Expected result
>>  0
>>  1
>>  2
>>  3

आवरण को उस डेटा को स्वीकार करने की आवश्यकता होती है जो उसे (जाहिर है) भेजा जाता है और StopIterationजब लूप समाप्त हो जाता है तो उसे भी संभालना चाहिए । जाहिर है बस कर for x in coro: yield xनहीं होगा। यहां एक संस्करण है जो काम करता है।

def writer_wrapper(coro):
    coro.send(None)  # prime the coro
    while True:
        try:
            x = (yield)  # Capture the value that's sent
            coro.send(x)  # and pass it to the writer
        except StopIteration:
            pass

या, हम ऐसा कर सकते थे।

def writer_wrapper(coro):
    yield from coro

यह कोड की 6 लाइनों को बचाता है, इसे बहुत अधिक पठनीय बनाता है और यह सिर्फ काम करता है। जादू!

जनरेटर उपज से डेटा भेजना - भाग 2 - अपवाद हैंडलिंग

इसे और जटिल बनाते हैं। क्या होगा यदि हमारे लेखक को अपवादों को संभालने की आवश्यकता है? मान लीजिए कि writerहैंडल एक है SpamExceptionऔर यह प्रिंट करता है ***अगर यह एक का सामना करता है।

class SpamException(Exception):
    pass

def writer():
    while True:
        try:
            w = (yield)
        except SpamException:
            print('***')
        else:
            print('>> ', w)

अगर हम नहीं बदले तो क्या होगा writer_wrapper? क्या यह काम करता है? कोशिश करते हैं

# writer_wrapper same as above

w = writer()
wrap = writer_wrapper(w)
wrap.send(None)  # "prime" the coroutine
for i in [0, 1, 2, 'spam', 4]:
    if i == 'spam':
        wrap.throw(SpamException)
    else:
        wrap.send(i)

# Expected Result
>>  0
>>  1
>>  2
***
>>  4

# Actual Result
>>  0
>>  1
>>  2
Traceback (most recent call last):
  ... redacted ...
  File ... in writer_wrapper
    x = (yield)
__main__.SpamException

उम, यह काम नहीं कर रहा है क्योंकि x = (yield)सिर्फ अपवाद उठाता है और सब कुछ एक दुर्घटनाग्रस्त पड़ाव पर आता है। चलो इसे काम करते हैं, लेकिन मैन्युअल रूप से अपवादों को संभालना और उन्हें भेजना या उन्हें उप-जनरेटर में फेंकना ( writer)

def writer_wrapper(coro):
    """Works. Manually catches exceptions and throws them"""
    coro.send(None)  # prime the coro
    while True:
        try:
            try:
                x = (yield)
            except Exception as e:   # This catches the SpamException
                coro.throw(e)
            else:
                coro.send(x)
        except StopIteration:
            pass

यह काम।

# Result
>>  0
>>  1
>>  2
***
>>  4

लेकिन ऐसा करता है!

def writer_wrapper(coro):
    yield from coro

yield fromपारदर्शी रूप से हैंडल मान भेज रहा है या उप जनरेटर में मूल्यों फेंक।

यह अभी भी सभी कोने के मामलों को कवर नहीं करता है। बाहरी जनरेटर बंद होने पर क्या होता है? उस मामले के बारे में जब उप-जनरेटर एक मान लौटाता है (हाँ, पायथन 3.3+ में, जनरेटर मान लौटा सकता है), रिटर्न मान का प्रचार कैसे किया जाना चाहिए? यह yield fromपारदर्शी रूप से सभी कोने के मामलों को वास्तव में प्रभावशाली बनाता हैyield fromबस जादुई काम करता है और उन सभी मामलों को संभालता है।

मुझे व्यक्तिगत रूप से लगता yield fromहै कि यह एक खराब कीवर्ड विकल्प है क्योंकि यह दो-तरफा प्रकृति को स्पष्ट नहीं करता है । अन्य खोजशब्द प्रस्तावित थे (जैसे delegateकि अस्वीकार कर दिए गए थे क्योंकि नए कीवर्ड को भाषा में जोड़ना मौजूदा लोगों के संयोजन की तुलना में बहुत अधिक कठिन है।

संक्षेप में, कॉल करने वाले और उप-जनरेटर के बीच के yield fromरूप में सोचना सबसे अच्छा है transparent two way channel

संदर्भ:

  1. पीईपी 380 - एक उप-जनरेटर (ईविंग) [v3.3, 2009-02-13] को सौंपने के लिए सिंटैक्स
  2. PEP 342 - संवर्धित जनरेटरों (GvR, Eby) के माध्यम से कोरआउट्स [v2.5, 2005-05-10]

3
@PraveenGollakota, अपने प्रश्न के दूसरे भाग में, एक जनरेटर (कोराउटाइन) से डेटा भेजना - भाग 1 से उपज का उपयोग करते हुए , क्या होगा यदि आपके पास प्राप्त आइटम को अग्रेषित करने के लिए कोरटाइन से अधिक है? एक ब्रॉडकास्टर या सब्सक्राइबर परिदृश्य की तरह जहां आप अपने उदाहरण में रैपर को कई कॉरआउट प्रदान करते हैं और उन सभी को आइटम भेजा जाना चाहिए या उनका सबसेट?
केविन गबोसी

3
@PraveenGollakota, महान जवाब के लिए यश। छोटे उदाहरणों ने मुझे उत्तर में चीजों को आज़माने की अनुमति दी। डेव बेज़ले पाठ्यक्रम के लिए लिंक एक बोनस था!
BiGYaN 18

1
कर except StopIteration: passअंदर while True:पाश का सही प्रतिनिधित्व नहीं है yield from coro- जो अनंत लूप नहीं है और बाद coro, शून्य हो जाता है (यानी StopIteration को जन्म देती है) writer_wrapperअगले स्टेटमेंट पर अमल होगा। आखिरी स्टेटमेंट के बाद यह StopIterationकिसी भी थका देने वाले जेनरेटर के रूप में ऑटो-बढ़ाएगा ...
Aprillion

1
... इसलिए यदि इसके बजाय writerनिहित for _ in range(4)है while True, तो >> 3इसे प्रिंट करने के बाद यह भी ऑटो-बढ़ाएगा StopIterationऔर यह ऑटो द्वारा संभाला जाएगा yield fromऔर फिर writer_wrapperऑटो-उठाएगा यह स्वयं का है StopIterationऔर क्योंकि ब्लॉक के wrap.send(i)अंदर नहीं है try, यह वास्तव में इस बिंदु पर उठाया जाएगा ( यानी ट्रेसबैक केवल लाइन को रिपोर्ट करेगा wrap.send(i), जेनरेटर के अंदर से कुछ भी नहीं)
Aprillion

3
पढ़ने पर " न्याय करना शुरू नहीं करता है ", मुझे पता है कि मैं सही उत्तर पर आया हूं। महान व्याख्या के लिए धन्यवाद!
Hot.PxL

89

ऐसी कौन सी परिस्थितियाँ हैं जहाँ "से उपज" उपयोगी है?

हर स्थिति जहां आपके पास एक लूप होता है:

for x in subgenerator:
  yield x

जैसा कि PEP वर्णन करता है, यह सबगेंनेटर का उपयोग करने के बजाय एक भोली कोशिश है, यह कई पहलुओं को याद कर रहा है, विशेष रूप से पीईपी 342 द्वारा शुरू की गई .throw()/ .send()/ .close()तंत्र की उचित हैंडलिंग । इसे ठीक से करने के लिए, बल्कि जटिल कोड आवश्यक है।

क्लासिक उपयोग मामला क्या है?

विचार करें कि आप पुनरावर्ती डेटा संरचना से जानकारी निकालना चाहते हैं। मान लें कि हम एक पेड़ में सभी पत्ती नोड्स प्राप्त करना चाहते हैं:

def traverse_tree(node):
  if not node.children:
    yield node
  for child in node.children:
    yield from traverse_tree(child)

इससे भी अधिक महत्वपूर्ण तथ्य यह है कि जब तक yield from, जनरेटर कोड को फिर से भरने का कोई सरल तरीका नहीं था। मान लीजिए कि आपके पास (संवेदनहीन) जेनरेटर है:

def get_list_values(lst):
  for item in lst:
    yield int(item)
  for item in lst:
    yield str(item)
  for item in lst:
    yield float(item)

अब आप इन लूपों को अलग-अलग जनरेटर में बदलने का निर्णय लेते हैं। इसके बिना yield from, यह बदसूरत है, उस बिंदु तक जहां आप दो बार सोचेंगे कि क्या आप वास्तव में इसे करना चाहते हैं। इसके साथ yield from, यह वास्तव में देखने में अच्छा है:

def get_list_values(lst):
  for sub in [get_list_values_as_int, 
              get_list_values_as_str, 
              get_list_values_as_float]:
    yield from sub(lst)

इसकी तुलना सूक्ष्म धागों से क्यों की जाती है?

मैं क्या सोचता हूँ पीईपी में यह खंड किस बारे में बात कर रहा है, हर जनरेटर का अपना अलग निष्पादन संदर्भ है। इस तथ्य के साथ कि जनरेटर-इटरेटर और कॉल करने वाले के बीच निष्पादन क्रमशः स्विच किया जाता है yieldऔर __next__(), क्रमशः, यह थ्रेड्स के समान है, जहां ऑपरेटिंग सिस्टम निष्पादन के संदर्भ के साथ-साथ निष्पादन के समय को समय-समय पर स्विच करता है (स्टैक, रजिस्टरों) ...)।

इस का प्रभाव भी तुलनीय है: जनरेटर-इटरेटर और कॉलर निष्पादन दोनों ही एक ही समय में अपनी निष्पादन स्थिति में होते हैं, उनके निष्पादन में हस्तक्षेप होता है। उदाहरण के लिए, यदि जनरेटर किसी प्रकार की गणना करता है और कॉलर परिणामों को प्रिंट करता है, तो जैसे ही वे उपलब्ध होंगे, आपको परिणाम दिखाई देंगे। यह संक्षिप्त रूप है।

यह सादृश्य कुछ खास नहीं है yield from, हालांकि - यह अजगर में जनरेटर की एक सामान्य संपत्ति है।


जनरेटरों को फिर से भरना आज दर्दनाक है।
जोश ली

1
मैं जेनरेटरों को पुन: उत्पन्न करने के लिए बहुत अधिक उपयोग करने की प्रवृत्ति रखता हूं (इटर्टूलसैचिन जैसे सामान), यह एक बड़ी बात नहीं है। मुझे पैदावार पसंद है, लेकिन मैं अभी भी यह देखने में विफल हूं कि यह कितना क्रांतिकारी है। यह शायद है, क्योंकि गुइडो इसके बारे में सब पागल है, लेकिन मुझे बड़ी तस्वीर याद आ रही है। मुझे लगता है कि यह भेजने के लिए बहुत अच्छा है () क्योंकि यह रिफ्लैक्टर के लिए कठिन है, लेकिन मैं इसका उपयोग अक्सर नहीं करता हूं।
ई-सिटिस

मुझे लगता है कि उन लोगों के get_list_values_as_xxxलिए एक एकल लाइन के साथ सरल जनरेटर हैं for x in input_param: yield int(x)और साथ अन्य दो क्रमशः strऔरfloat
madtyn

@NiklasB। "पुनरावर्ती डेटा संरचना से जानकारी निकालें"। मैं सिर्फ डेटा के लिए Py में जा रहा हूं। क्या आप इस क्यू में एक स्टैब ले सकते हैं ?
अलंकालविटि

33

जहाँ भी आप किसी जनरेटर के भीतर से एक जनरेटर का आह्वान करते हैं, आपको फिर yieldसे मानों को "पंप" की आवश्यकता होती है for v in inner_generator: yield v:। जैसा कि पीईपी बताते हैं कि इसमें सूक्ष्म जटिलताएं हैं जिन्हें ज्यादातर लोग नजरअंदाज कर देते हैं। throw()पीईपी में गैर-स्थानीय प्रवाह-नियंत्रण एक उदाहरण है। नए सिंटैक्स yield from inner_generatorका उपयोग तब किया जाता है जहां आपने forपहले स्पष्ट लूप लिखा होगा । यह महज सिंथैटिक शुगर नहीं है, हालांकि: यह उन सभी कोनों को हैंडल करता है जिन्हें forलूप द्वारा अनदेखा किया जाता है। "शर्करा" होने के कारण लोगों को इसका उपयोग करने के लिए प्रोत्साहित किया जाता है और इस प्रकार सही व्यवहार मिलता है।

चर्चा थ्रेड में यह संदेश इन जटिलताओं के बारे में बात करता है:

PEP 342 द्वारा शुरू की गई अतिरिक्त जनरेटर सुविधाओं के साथ, अब ऐसा नहीं है: जैसा कि ग्रेग के पीईपी में वर्णित है, सरल पुनरावृत्ति भेजने () और फेंक () को सही ढंग से समर्थन नहीं करता है। जिम्नास्टिक को भेजने () और थ्रो को सपोर्ट करने की जरूरत होती है, जब आप उन्हें तोड़ते हैं तो वास्तव में वह कॉम्प्लेक्स नहीं होता है, लेकिन वे या तो तुच्छ नहीं होते हैं।

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

नया yield fromसिंटैक्स थ्रेडिंग के मामले में भाषा में कोई अतिरिक्त क्षमता नहीं जोड़ता है, यह सिर्फ मौजूदा सुविधाओं का सही तरीके से उपयोग करना आसान बनाता है। या अधिक सटीक रूप से यह एक जटिल आंतरिक जनरेटर के नौसिखिए उपभोक्ता के लिए आसान बनाता है, जो किसी विशेषज्ञ द्वारा उस जनरेटर से गुजरने के बिना अपनी किसी भी जटिल विशेषता को तोड़ता है।


23

एक छोटा उदाहरण आपको किसी yield fromउपयोग के मामले को समझने में मदद करेगा : दूसरे जनरेटर से मूल्य प्राप्त करें

def flatten(sequence):
    """flatten a multi level list or something
    >>> list(flatten([1, [2], 3]))
    [1, 2, 3]
    >>> list(flatten([1, [2], [3, [4]]]))
    [1, 2, 3, 4]
    """
    for element in sequence:
        if hasattr(element, '__iter__'):
            yield from flatten(element)
        else:
            yield element

print(list(flatten([1, [2], [3, [4]]])))

2
बस यह सुझाव देना चाहता था कि अंत में प्रिंट एक सूची में रूपांतरण के बिना थोड़ा अच्छा लगेगा -print(*flatten([1, [2], [3, [4]]]))
yoniLavi

6

yield from एक कुशल तरीके से मूल रूप से श्रृंखला पुनरावृत्तियों:

# chain from itertools:
def chain(*iters):
    for it in iters:
        for item in it:
            yield item

# with the new keyword
def chain(*iters):
    for it in iters:
        yield from it

जैसा कि आप देख सकते हैं कि यह एक शुद्ध पायथन लूप को हटा देता है। यह सब बहुत कुछ करता है, लेकिन पुनरावृत्तियों का पीछा करना पायथन में एक बहुत ही सामान्य पैटर्न है।

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

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

अधिक विवरण के लिए पायथन में कोरटाइन के बारे में इस उत्कृष्ट ट्यूटोरियल को पढ़ें


10
यह उत्तर भ्रामक है क्योंकि यह "उपज से" की मुख्य विशेषता को बताता है, जैसा कि ऊपर बताया गया है: भेजें () और फेंक () समर्थन।
जस्टिन डब्ल्यू

2
@ जस्टिन डब्ल्यू: मुझे लगता है कि आप जो कुछ भी पढ़ते हैं वह वास्तव में भ्रामक है, क्योंकि आपको वह बिंदु नहीं मिला है जो throw()/send()/close()ऐसी yieldविशेषताएं हैं जो yield fromस्पष्ट रूप से ठीक से लागू करना है क्योंकि यह कोड को सरल बनाने के लिए माना जाता है। इस तरह की तुच्छताओं का उपयोग से कोई लेना-देना नहीं है।
जोचेन रिट्जेल

5
क्या आप बेन जैक्सन के जवाब पर विवाद कर रहे हैं? आपके उत्तर के बारे में मेरा पठन यह है कि यह अनिवार्य रूप से वाक्यगत चीनी है जो आपके द्वारा प्रदान किए गए कोड परिवर्तन के बाद है। बेन जैक्सन का जवाब विशेष रूप से उस दावे का खंडन करता है।
जस्टिन डब्ल्यू

@JochenRitzel आपको अपना chainफ़ंक्शन लिखने की आवश्यकता नहीं है क्योंकि itertools.chainपहले से मौजूद है। का उपयोग करें yield from itertools.chain(*iters)
एक्यूमेनस

3

के लिए आवेदन किया है उपयोग में अतुल्यकालिक आईओ coroutine , yield fromके रूप में एक समान व्यवहार है awaitएक में coroutine समारोह । दोनों का उपयोग कोरटाइन के निष्पादन को निलंबित करने के लिए किया जाता है।

Asyncio के लिए, यदि पुराने Python संस्करण (यानी> 3.5) का समर्थन करने की कोई आवश्यकता नहीं है, तो async def/ awaitएक coroutine को परिभाषित करने के लिए अनुशंसित सिंटैक्स है। इस प्रकार yield fromअब धनिया की जरूरत नहीं है।

लेकिन सामान्य तौर पर एसिंसीओ के बाहर, yield from <sub-generator>अभी भी उप-जनरेटर को पुनरावृत्त करने में कुछ अन्य उपयोग हैं जैसा कि पहले उत्तर में बताया गया है।


1

यह कोड एक फ़ंक्शन को परिभाषित करता है जो fixed_sum_digitsसभी छह अंकों की संख्या को गणना करने वाले जनरेटर को लौटाता है जैसे कि अंकों का योग 20 है।

def iter_fun(sum, deepness, myString, Total):
    if deepness == 0:
        if sum == Total:
            yield myString
    else:  
        for i in range(min(10, Total - sum + 1)):
            yield from iter_fun(sum + i,deepness - 1,myString + str(i),Total)

def fixed_sum_digits(digits, Tot):
    return iter_fun(0,digits,"",Tot) 

इसके बिना लिखने का प्रयास करें yield from । यदि आप इसे करने का एक प्रभावी तरीका पाते हैं तो मुझे बताएं।

मुझे लगता है कि इस तरह के मामलों के लिए: पेड़ों का दौरा करना, yield fromकोड को सरल और क्लीनर बनाता है।


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