অনুশীলনে, পাইথন ৩.৩-এ নতুন "উপার্জন" সিনট্যাক্সের মূল ব্যবহারগুলি কী?


407

পিইপি 380 এর চারপাশে আমার মস্তিষ্ককে জড়িয়ে ফেলার জন্য আমার খুব কষ্ট হচ্ছে ।

  1. "ফলন" থেকে দরকারী এমন পরিস্থিতি কী?
  2. ক্লাসিক ব্যবহারের ক্ষেত্রে কী?
  3. কেন এটি মাইক্রো-থ্রেডগুলির সাথে তুলনা করা হয়?

[ হালনাগাদ ]

এখন আমি বুঝতে পারি আমার অসুবিধার কারণ। আমি জেনারেটর ব্যবহার করেছি, তবে সত্যিকারের কখনও কর্টিন ব্যবহার করেনি ( পিইপি -342 দ্বারা প্রবর্তিত )। কিছু সাদৃশ্য থাকা সত্ত্বেও, জেনারেটর এবং কর্টিনগুলি মূলত দুটি ভিন্ন ধারণা। নতুন সিনট্যাক্স বোঝার মূল বিষয় কর্টাইনগুলি (কেবল জেনারেটর নয়) the

আইএমএইচও কর্টিনগুলি সর্বাধিক অস্পষ্ট পাইথন বৈশিষ্ট্য , বেশিরভাগ বই এটিকে অকেজো এবং উদ্দীপনা দেখাবে।

দুর্দান্ত উত্তরের জন্য ধন্যবাদ, তবে ডেভিড বেজলি উপস্থাপনাগুলির সাথে লিঙ্কযুক্ত এএফএফ এবং তার মন্তব্যে বিশেষ ধন্যবাদ । ডেভিড পাথর।



7
ডেভিড বেজলির ডাবিজ.com/coroutines উপস্থাপনার ভিডিও : youtube.com/watch?v=Z_OAlIhXziw
jcugat

উত্তর:


570

প্রথমে একটি জিনিস বের করা যাক। যে ব্যাখ্যাটির yield from gসমতুল্য for v in g: yield v তা এমনকি যা ন্যায়বিচার তা yield fromকরা শুরু করে না । কারণ, আসুন আমরা এটির মুখোমুখি হই, যদি সমস্ত yield fromকিছু forলুপকে প্রসারিত করে , তবে এটি yield fromভাষায় যুক্ত হওয়ার নিশ্চয়তা দেয় না এবং পাইথন ২.x এ প্রয়োগ করা থেকে পুরো নতুন বৈশিষ্ট্যগুলিকে পুরোপুরি আটকাতে পারে।

এটি কী yield fromকরে এটি কলার এবং সাব-জেনারেটরের মধ্যে স্বচ্ছ দ্বিদ্বি সংযোগ স্থাপন করে :

  • সংযোগটি "স্বচ্ছ" এই অর্থে যে এটি সমস্ত কিছু সঠিকভাবে প্রচার করবে, কেবলমাত্র উপাদান তৈরি হচ্ছে না (যেমন ব্যতিক্রমগুলি প্রচারিত হয়)।

  • সংযোগ "দ্বিমুখী", এই অর্থে ডাটা উভয় পাঠানো যেতে পারে যে থেকে এবং থেকে জেনারেটরের।

( যদি আমরা টিসিপি নিয়ে কথা বলছিলাম, এর yield from gঅর্থ হতে পারে "এখন আমার ক্লায়েন্টের সকেট অস্থায়ীভাবে সংযোগ বিচ্ছিন্ন করুন এবং এটিকে অন্য সার্ভার সকেটে পুনরায় সংযুক্ত করুন" ))

BTW, যদি আপনি নিশ্চিত না কি জেনারেটরের থেকে ডেটা প্রেরণ , আপনি সবকিছু ড্রপ এবং প্রায় পড়া প্রয়োজন এমনকি উপায়ে coroutines প্রথম they're খুব দরকারী (তাদের বিপরীতে সাবরুটিনের ), কিন্তু দুর্ভাগ্যবশত পাইথন মধ্যে স্বল্প-পরিচিত। ডেভ বিজলির কৌতূহল কোর্স কর্টাইনগুলিতে একটি দুর্দান্ত শুরু। দ্রুত প্রাইমারের জন্য স্লাইডগুলি 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যা এতে প্রেরিত ডেটা গ্রহণ করে এবং একটি সকেট, এফডি ইত্যাদিতে লেখেন etc.

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স্বচ্ছভাবে হ্যান্ডলগুলি মান পাঠানো বা উপ-জেনারেটরের মধ্যে মান নিক্ষেপ।

এটি এখনও সমস্ত কোণার কেসটি কভার করে না। বাইরের জেনারেটর বন্ধ থাকলে কী হবে? সাব-জেনারেটর যখন মান দেয় (তবে হ্যাঁ, পাইথন ৩.৩++ তে জেনারেটর মান ফিরিয়ে দিতে পারে) সেই ক্ষেত্রে কী হবে, কীভাবে ফেরতের মান প্রচার করা উচিত? যে yield fromস্বচ্ছভাবে সমস্ত কোণার কেস পরিচালনা করে সত্যই চিত্তাকর্ষকyield fromকেবল ম্যাজিকালি কাজ করে এবং এই সমস্ত কেস পরিচালনা করে।

আমি ব্যক্তিগতভাবে মনে করি yield fromএকটি দুর্বল কীওয়ার্ড পছন্দ কারণ এটি দ্বিমুখী প্রকৃতিটিকে দৃশ্যমান করে না। প্রস্তাবিত অন্যান্য কীওয়ার্ড ছিল (যেমন delegateতবে প্রত্যাখ্যান করা হয়েছিল কারণ ভাষাতে একটি নতুন কীওয়ার্ড যুক্ত করা বিদ্যমান শব্দগুলির সংমিশ্রণের চেয়ে অনেক বেশি কঠিন।

সংক্ষেপে, এ yield fromহিসাবে ভাবাই ভালtransparent two way channel কলার এবং সাব-জেনারেটরের মধ্যে ।

তথ্যসূত্র:

  1. পিইপি 380 - উপ-জেনারেটর (ইউইং) -কে অর্পণ করার জন্য সিনট্যাক্স [v3.3, 2009-02-13]
  2. পিইপি 342 - বর্ধিত জেনারেটর (জিভিআর, এবি) এর মাধ্যমে কর্টিনগুলি [v2.5, 2005-05-10]

3
@ প্রবীণগোলকোটা, আপনার প্রশ্নের দ্বিতীয় অংশে, - জেনারেটরের কাছে ডেটা প্রেরণ (কর্টিন) - ভাগ 1 থেকে প্রাপ্ত , যদি আপনার প্রাপ্ত কাউকে দিয়ে ফরোয়ার্ড করার জন্য কর্টিনের চেয়ে বেশি থাকে? ব্রডকাস্টার বা গ্রাহক দৃশ্যের মতো যেখানে আপনি আপনার উদাহরণের মোড়কে একাধিক কর্টিন সরবরাহ করেন এবং আইটেমগুলি সেগুলিতে সমস্ত পাঠানো উচিত বা সেগুলি সাবসেট করা উচিত?
কেভিন ঘাবুসি

3
দুর্দান্ত উত্তরের জন্য @ প্রবীণগোলাকোটা, কুডোস। ছোট উদাহরণগুলি আমাকে প্রতিস্থাপনে জিনিসগুলি দেখতে দেয়। ডেভ বিজলি কোর্সে লিঙ্কটি ছিল বোনাস!
বিজিওয়ান

1
করছেন except StopIteration: passভিতরে while True:লুপ সঠিক উপস্থাপনা নয় yield from coro- যা একটি অসীম লুপ নয় এবং পরে coro, ক্লান্ত (অর্থাত StopIteration উত্থাপন) writer_wrapperপরবর্তী প্রতিবেদনটি চালানো হবে। শেষ বিবৃতি দেওয়ার পরে এটি StopIterationকোনও ক্লান্ত জেনারেটর হিসাবে স্বয়ংক্রিয়ভাবে উত্থাপন করবে ...
এপ্রিলিয়ন

1
... সুতরাং পরিবর্তে যদি এটি writerঅন্তর্ভুক্ত থাকে তবে মুদ্রণের পরে এটি স্বয়ংক্রিয়ভাবে উত্থাপিত হবে এবং এটি স্বয়ংক্রিয়ভাবে পরিচালিত হবে এবং তারপরে এটি স্বয়ংক্রিয়ভাবে উত্থাপন করবে এবং কারণ এটি ব্লকের ভিতরে নেই , এটি আসলে এই মুহুর্তে উত্থাপিত হবে ( অর্থাত্ ট্রেসব্যাক জেনারেটরের ভিতরে থেকে কিছুই নয়, কেবল লাইনটির প্রতিবেদন করবেfor _ in range(4)while True>> 3StopIterationyield fromwriter_wrapperStopIterationwrap.send(i)trywrap.send(i)
এপ্রিলিয়ন

3
" ন্যায়বিচার করা শুরু করে না " পড়ার পরে , আমি জানি আমি সঠিক উত্তরে এসেছি। মহান ব্যাখ্যা জন্য আপনাকে ধন্যবাদ!
হট.পেক্সএল

89

"ফলন" থেকে দরকারী এমন পরিস্থিতি কী?

প্রতিটি পরিস্থিতি যেখানে আপনার মতো লুপ রয়েছে:

for x in subgenerator:
  yield x

PEP বর্ণনা, এই বরং একটি সরল প্রয়াস subgenerator ব্যবহার, এটি বিভিন্ন দিক অনুপস্থিত, বিশেষ করে যথাযথ হ্যান্ডলিং হয় .throw()/ .send()/ .close()চালু প্রক্রিয়া PEP 342 । এটি সঠিকভাবে করার জন্য, জটিল কোডটি প্রয়োজনীয়।

ক্লাসিক ব্যবহারের ক্ষেত্রে কী?

বিবেচনা করুন যে আপনি একটি পুনরাবৃত্ত তথ্য কাঠামো থেকে তথ্য নিষ্কাশন করতে চান। ধরা যাক আমরা একটি গাছের মধ্যে সমস্ত পাতা নোড পেতে চাই:

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, এটি কুরুচিপূর্ণ, আপনি যেখানে আপনি এটি করতে চান কিনা তা আপনি দ্বিগুণ ভাবেন up সহ 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
ম্যাডটেন

@NiklasB। পুনরায় "পুনরাবৃত্ত হওয়া তথ্য কাঠামো থেকে তথ্য আহরণ করুন।" আমি কেবল ডেটার জন্য পাইতে যাচ্ছি। আপনি কি এই প্রশ্নে ছুরিকাঘাত করতে পারেন ?
অ্যালানচলভিট্টি

33

আপনি যেখানেই জেনারেটরের মধ্য থেকে জেনারেটরটি চালু করেন yieldসেখানে মানগুলি পুনরায় প্রয়োগ করতে আপনার একটি "পাম্প" প্রয়োজন for v in inner_generator: yield v। পিইপি নির্দেশ করে যেহেতু এর মধ্যে সূক্ষ্ম জটিলতা রয়েছে যা বেশিরভাগ লোকেরা উপেক্ষা করে। অ-স্থানীয় প্রবাহ নিয়ন্ত্রণ যেমন throw()পিইপিতে দেওয়া উদাহরণ is নতুন সিনট্যাক্সটি yield from inner_generatorআপনি যেখানে forআগে সুস্পষ্ট লুপ লিখেছেন সেখানে ব্যবহৃত হয় । এটি নিছক সিনট্যাকটিক চিনি নয়, যদিও: forলুপ দ্বারা উপেক্ষা করা কোণার সমস্ত ক্ষেত্রে এটি পরিচালনা করে । "মিষ্টি" হওয়া মানুষকে এটি ব্যবহার করতে উত্সাহ দেয় এবং এভাবে সঠিক আচরণ পেতে।

আলোচনার সুত্রে এই বার্তাটি এই জটিলতাগুলি সম্পর্কে আলোচনা করে:

পিইপি 342 দ্বারা প্রবর্তিত অতিরিক্ত জেনারেটর বৈশিষ্ট্যগুলির সাথে, এটি আর নেই: গ্রেগের পিইপিতে বর্ণিত হিসাবে, সরল পুনরাবৃত্তি প্রেরণ () এবং নিক্ষেপ () সঠিকভাবে সমর্থন করে না। জিমন্যাস্টিকগুলি প্রেরণ () এবং নিক্ষেপ () ছুঁড়তে সহায়তা করার জন্য প্রয়োজনীয় ছিল যখন আপনি সেগুলি ভেঙে ফেলেন আসলে তা জটিল নয়, তবে সেগুলিও তুচ্ছ নয়।

আমি একটি কথা বলতে না পারেন, তুলনা মাইক্রো-থ্রেড সঙ্গে, অন্যান্য পালন করার চেয়ে যে জেনারেটর paralellism এক ধরনের আছে। আপনি স্থগিত জেনারেটরটিকে একটি থ্রেড হিসাবে বিবেচনা করতে পারেন যা yieldগ্রাহক থ্রেডের মাধ্যমে মান প্রেরণ করে । আসল বাস্তবায়ন এর মতো কিছুই নাও হতে পারে (এবং প্রকৃত বাস্তবায়ন স্পষ্টতই পাইথন বিকাশকারীদের পক্ষে খুব আগ্রহের বিষয়) তবে এটি ব্যবহারকারীদের উদ্বেগের নয়।

নতুন yield fromসিনট্যাক্স থ্রেডিংয়ের ক্ষেত্রে ভাষার কোনও অতিরিক্ত ক্ষমতা যুক্ত করে না, এটি বিদ্যমান বৈশিষ্ট্যগুলি সঠিকভাবে ব্যবহার করা সহজ করে তোলে। বা আরও স্পষ্ট করে বলা যায় যে কোনও বিশেষজ্ঞের লেখা কোনও জটিল অভ্যন্তর জেনারেটরের একজন নবজাতক গ্রাহকের পক্ষে তার কোনও জটিল বৈশিষ্ট্য ভঙ্গ না করেই সেই জেনারেটরের মধ্য দিয়ে যাওয়া সহজ করে তোলে ।


23

একটি সংক্ষিপ্ত উদাহরণ আপনাকে যে কোনও একটি yield fromব্যবহারের কেস বুঝতে সাহায্য করবে : অন্য জেনারেটরের কাছ থেকে মান পেতে get

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]]]))
লাগবে

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
আপনি কি উপরে বেন জ্যাকসনের উত্তর বিতর্ক করছেন? আপনার উত্তরের আমার পড়াটি হ'ল এটি মূলত সিনট্যাকটিক চিনি যা আপনার সরবরাহিত কোড রূপান্তরকে অনুসরণ করে। বেন জ্যাকসনের উত্তর বিশেষত সেই দাবিটিকে খণ্ডন করে।
জাস্টিন ডাব্লু

@ জোচেনরেটজেল আপনার নিজের chainফাংশনটি লেখার দরকার itertools.chainনেই কারণ ইতিমধ্যে বিদ্যমান। ব্যবহার yield from itertools.chain(*iters)
একিউম্যানাস

3

অ্যাসিঙ্ক্রোনাস আইও কর্টিনের জন্য প্রয়োগ ব্যবহারে , কর্টিন ফাংশনেরyield from মতোই আচরণ করা awaitহয় । যার দুটিই কর্টিনের কার্যকারিতা স্থগিত করার জন্য ব্যবহৃত হয়।

অ্যাসিনসিওর জন্য, যদি পুরনো পাইথন সংস্করণ (যেমন> 3.5) সমর্থন করার প্রয়োজন না হয় তবে async def/ awaitকর্টিন সংজ্ঞায়িত করার জন্য প্রস্তাবিত বাক্য গঠন। সুতরাং 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কোডটি সহজ এবং পরিষ্কার করে তোলে।


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.