কিভাবে জেনারেটর থেকে কেবল একটি আইটেম বাছাই?


213

নিম্নলিখিতগুলির মতো আমার একটি জেনারেটর ফাংশন রয়েছে:

def myfunct():
  ...
  yield result

এই ফাংশনটি কল করার স্বাভাবিক উপায়টি হ'ল:

for r in myfunct():
  dostuff(r)

আমার প্রশ্ন, আমি যখনই চাই জেনারেটর থেকে কেবল একটি উপাদান পাওয়ার কোনও উপায় আছে? উদাহরণস্বরূপ, আমি কিছু করতে চাই:

while True:
  ...
  if something:
      my_element = pick_just_one_element(myfunct())
      dostuff(my_element)
  ...

উত্তর:


304

ব্যবহার করে একটি জেনারেটর তৈরি করুন

g = myfunct()

প্রতিবার আপনি কোনও আইটেম চাইবেন, ব্যবহার করুন

next(g)

(বা g.next()পাইথন 2.5 বা নীচে)।

যদি জেনারেটরটি প্রস্থান করে, এটি উত্থাপন করবে StopIteration। প্রয়োজনে আপনি এই ব্যতিক্রমটি ধরতে পারেন, বা defaultযুক্তিটি এতে ব্যবহার করতে পারেন next():

next(g, default_value)

4
দ্রষ্টব্য, এটি কেবলমাত্র স্টপআইটারেশন বাড়িয়ে তুলবে যখন আপনি g এ শেষ আইটেম সরবরাহ করার পরে g.next () ব্যবহার করার চেষ্টা করবেন।
ওয়াইল্ডক

26
next(gen, default)StopIterationব্যতিক্রম এড়াতেও ব্যবহৃত হতে পারে । উদাহরণস্বরূপ next(g, None)স্ট্রিংগুলির একটি জেনারেটর হয় হয় স্ট্রিং দেয় বা পুনরাবৃত্তি শেষ হওয়ার পরে কোনও কিছুই পাওয়া যায় না।
আটটিলা

8
পাইথন 3000 এ, পরের () __ পরবর্তী __ ()
জোনাথন বাল্ডউইন

27
@ জোনাথন বাল্ডউইন: আপনার মন্তব্য কিছুটা বিভ্রান্তিকর। পাইথন 3 এ, আপনি আমার উত্তরে প্রদত্ত দ্বিতীয় বাক্য গঠনটি ব্যবহার করবেন next(g),। এই অভ্যন্তরীণভাবে ডাকব g.__next__(), কিন্তু আপনি সত্যিই সেটা নিয়ে চিন্তা করতে হবে না আপনি সাধারণত পরোয়া করি না ঠিক যেমন যে len(a)অভ্যন্তরীণভাবে কল a.__len__()
সোভেন মারনাচ

14
আমার আরো স্পষ্ট করা উচিত। পাই 3 g.next()কে g.__next__()আছে Builtin next(iterator)পাইথন 2.6 যেহেতু হয়েছে প্রায়, এবং কি সব নতুন পাইথন কোড ব্যবহার করা উচিত, এবং এটি backimplement তুচ্ছ যদি তুমি PY <= 2.5 সমর্থন করার জন্য প্রয়োজন।
জোনাথন বাল্ডউইন

29

একটি জেনারেটর ব্যবহারের মাত্র একটি উপাদান বাছাইয়ের জন্য breakএকটি forবিবৃতিতে , বাlist(itertools.islice(gen, 1))

আপনার উদাহরণ অনুসারে (আক্ষরিক) আপনি যেমন কিছু করতে পারেন:

while True:
  ...
  if something:
      for my_element in myfunct():
          dostuff(my_element)
          break
      else:
          do_generator_empty()

যদি আপনি চান " [একবারে উত্পন্ন] জেনারেটর থেকে যখনই আমি চাই কেবলমাত্র একটি উপাদান পান " (আমি মনে করি যে 50% আসল অভিপ্রায় এবং সবচেয়ে সাধারণ উদ্দেশ্যটি বোঝায়) তবে:

gen = myfunct()
while True:
  ...
  if something:
      for my_element in gen:
          dostuff(my_element)
          break
      else:
          do_generator_empty()

এইভাবে স্পষ্টভাবে ব্যবহার generator.next() এড়ানো যায় এবং ইনপুট হ্যান্ডলিংয়ের জন্য (ক্রিপ্টিক) StopIterationব্যতিক্রম হ্যান্ডলিং বা অতিরিক্ত ডিফল্ট মান তুলনা প্রয়োজন হয় না।

দ্য else:এর forবিবৃতি বিভাগে প্রয়োজন হয় যদি আপনি শেষ অফ জেনারেটরের ক্ষেত্রে বিশেষ কিছু চাই না।

নোট অন next() / .next():

পাইথন 3-তে সঠিক কারণে এই .next()পদ্ধতির নামকরণ করা হয়েছিল .__next__(): এটি নিম্ন-স্তরের হিসাবে বিবেচিত হয় (পিইপি 3114)। পাইথন ২.6 এর পূর্বে বিল্টিন ফাংশনটির next()অস্তিত্ব ছিল না। এমনকি এটি সরানো নিয়েও আলোচনা হয়েছিলnext()operator এটির বিরল প্রয়োজন এবং বিল্টিন নামগুলির প্রশ্নবিদ্ধ মুদ্রাস্ফীতিের কারণে মডিউলটিতে (যা জ্ঞানী হতে পারে) হওয়ার ।

next()ডিফল্ট ছাড়াই ব্যবহার করা এখনও খুব নিম্ন-স্তরের অনুশীলন - StopIterationসাধারণ অ্যাপ্লিকেশন কোডটিতে খোলামেলাভাবে নীল থেকে বল্টারের মতো ক্রিপ্টিক ছুঁড়ে দেওয়া । এবং next()ডিফল্ট সেন্ডিনেলটি ব্যবহার করে - কোনটির জন্য সেরা বিকল্পটি হওয়া উচিতnext() সরাসরি সরাসরি builtinsপ্রবেশের - এটি সীমাবদ্ধ এবং প্রায়শই অদ্ভুত অ-পাইথোনিক যুক্তি / পাঠযোগ্যতার কারণ দেয়।

নীচের লাইন: পরবর্তী () ব্যবহার করা খুব বিরল হওয়া উচিত - যেমন operatorমডিউলটির ফাংশনগুলি ব্যবহার করা । ব্যবহার for x in iterator, islice, list(iterator)সম্ভব এবং বেশ সবসময় - এবং অন্যান্য কার্যাবলী অঙ্গীভূতভাবে কোনো ইটারেটরে গ্রহণ আবেদন স্তরের উপর iterators ব্যবহারের প্রাকৃতিক উপায়। next()নিম্ন-স্তরের, একটি অতিরিক্ত ধারণা, নিখরচায় - যেমন এই থ্রেডের প্রশ্নটি দেখায়। ব্যবহার করার সময় যেমন breakমধ্যে forপ্রচলিত আছে।


8
তালিকার প্রথম ফলাফলের প্রথম উপাদানটি অর্জনের জন্য এটি খুব বেশি কাজ। প্রায়শই যথেষ্ট আমার অলস হওয়ার দরকার নেই তবে পাই 3-তে কোনও পছন্দ নেই। এর মতো কিছু নেই কি mySeq.head?
জাভাদবা

2

আমি বিশ্বাস করি না যে জেনারেটর থেকে একটি স্বেচ্ছাসেবক মান পুনরুদ্ধার করার একটি সুবিধাজনক উপায় আছে। জেনারেটর নিজেই অতিক্রম করার জন্য একটি পরবর্তী () পদ্ধতি সরবরাহ করবে, কিন্তু স্মৃতি সংরক্ষণ করার জন্য সম্পূর্ণ ক্রমটি তত্ক্ষণাত প্রস্তুত করা হয়নি। এটি একটি জেনারেটর এবং একটি তালিকার মধ্যে কার্যকরী পার্থক্য।


1

পাইথন 3 এর সম্পূর্ণ কাজের উদাহরণের জন্য এই উত্তরগুলির মাধ্যমে আপনারা যা স্ক্যান করছেন তাদের জন্য ... এখানে ভাল আপনি এখানে যান:

def numgen():
    x = 1000
    while True:
        x += 1
        yield x

nums = numgen() # because it must be the _same_ generator

for n in range(3):
    numnext = next(nums)
    print(numnext)

এই ফলাফলগুলি:

1001
1002
1003

1

জেনারেটর একটি ফাংশন যা একটি পুনরুক্তি উত্পাদন করে। অতএব, একবার আপনার পুনরাবৃত্তি উদাহরণ থাকলে, পুনরুক্তিকারী থেকে পরবর্তী আইটেম আনতে পরবর্তী () ব্যবহার করুন । উদাহরণস্বরূপ, প্রথম আইটেম আনতে পরবর্তী () ফাংশনটি ব্যবহার করুন এবং পরে for inঅবশিষ্ট আইটেমগুলি প্রক্রিয়া করতে ব্যবহার করুন :

# create new instance of iterator by calling a generator function
items = generator_function()

# fetch and print first item
first = next(items)
print('first item:', first)

# process remaining items:
for item in items:
    print('next item:', item)


-3

আমি বিশ্বাস করি যে একমাত্র উপায় হ'ল পুনরাবৃত্তির কাছ থেকে একটি তালিকা পেতে তারপরে সেই তালিকা থেকে আপনার পছন্দসই উপাদানটি পান।

l = list(myfunct())
l[4]

সোভেনের উত্তর সম্ভবত আরও ভাল, তবে আমি এটি এখানেই রেখে দেব যদি না এটি আপনার প্রয়োজনের সাথে আরও ইনলাইন থাকে।
keegan3d

26
এটি করার আগে আপনার সসীম জেনারেটর রয়েছে তা নিশ্চিত করুন।
শেঠ

6
দুঃখিত, এটির পুনরাবৃত্তির দৈর্ঘ্য জটিলতা রয়েছে, যখন সমস্যাটি অবশ্যই ও (1)।
yo

1
জেনারেটর থেকে স্তন্যপান করতে অনেক বেশি মেমরি এবং প্রক্রিয়া নষ্ট করছে! এছাড়াও, যেমন @ পূর্বে উল্লেখ করা হয়েছে, জেনারেটরগুলির গ্যারান্টি দেওয়া হয় না, কখন উত্পাদন বন্ধ করা যায়।
পাইওভার

এটা স্পষ্টতই না একমাত্র উপায় (অথবা সবচেয়ে ভালো উপায় যদি myfunct()মূল্যবোধের সংখ্যক উত্পন্ন) যেহেতু আপনি ব্যবহার করতে পারেন বিল্ট-ইন ফাংশন nextপরবর্তী উত্পন্ন মান জন্য।
হ্যালো গুডবাই
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.