আপনি পাইথন জেনারেটরের জন্য কী ব্যবহার করতে পারেন?


213

আমি পাইথন শিখতে শুরু করেছি এবং আমি জেনারেটরের ফাংশনগুলি পেরিয়ে এসেছি, সেগুলিতে ফলন বিবরণী রয়েছে। এই ধরণের ফাংশনগুলি সমাধান করার ক্ষেত্রে কী ধরণের সমস্যাগুলি সত্য তা আমি জানতে চাই।


6
সম্ভবত আরও ভাল প্রশ্ন হতে পারে যখন আমাদের
ইএম

1
বাস্তব বিশ্বের উদাহরণ এখানে
গিরি

উত্তর:


239

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

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

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

উদাহরণস্বরূপ, বলুন আপনি একটি 'ফাইল সিস্টেম অনুসন্ধান' প্রোগ্রাম লিখেছেন। আপনি অনুসন্ধানটি সম্পূর্ণরূপে সম্পাদন করতে পারবেন, ফলাফল সংগ্রহ করতে পারেন এবং তারপরে একবারে এটি প্রদর্শন করতে পারেন। আপনি প্রথমটি দেখানোর আগে সমস্ত ফলাফল সংগ্রহ করতে হবে এবং ফলাফলগুলি একই সাথে স্মৃতিতে থাকবে। অথবা ফলাফলগুলি খুঁজে পাওয়ার সময় আপনি ফলাফলগুলি প্রদর্শন করতে পারেন যা ব্যবহারকারীর প্রতি আরও মেমরির দক্ষ এবং অনেক বেশি বন্ধুত্বপূর্ণ হবে। পরবর্তীটি ফাইল-সিস্টেম-অনুসন্ধান ফাংশনে ফলাফল-প্রিন্টিং ফাংশনটি পাস করার মাধ্যমে করা যেতে পারে, বা এটি কেবল অনুসন্ধান ফাংশনটিকে একটি জেনারেটর তৈরি করে এবং ফলাফলটি পুনরাবৃত্তি করেই করা যেতে পারে।

যদি আপনি দ্বিতীয় দুটি পদ্ধতির উদাহরণ দেখতে চান তবে, os.path.walk () (কলব্যাক সহ পুরানো ফাইল সিস্টেম-ওয়াকিং ফাংশন) এবং ওএসওয়াক () (নতুন ফাইলসিস্টেম-ওয়াকিং জেনারেটর দেখুন see) অবশ্যই দেখুন, আপনি সত্যিই একটি তালিকার সমস্ত ফলাফল সংগ্রহ করতে চেয়েছিলেন, জেনারেটর পদ্ধতির বড় তালিকা পদ্ধতির রূপান্তর করার জন্য নগণ্য:

big_list = list(the_generator)

ফাইল সিস্টেমের তালিকা তৈরি করে এমন কোনও জেনারেটর কি সেই লুপের মধ্যে সেই জেনারেটরটি চালিত কোডের সমান্তরালে ক্রিয়া সম্পাদন করে? আদর্শভাবে কম্পিউটারটি লুপটির বডি চালিত করে (শেষ ফলাফলটি প্রক্রিয়াজাত করে) একযোগে জেনারেটরকে পরবর্তী মানটি পেতে যা করতে হবে তা করে।
স্টিভেন লু

@ স্টিভেনলু: পরবর্তী ফলাফল পাওয়ার পরে yieldএবং তার আগে ম্যানুয়ালি থ্রেডগুলি চালিত করতে সমস্যা না হলে এটি joinসমান্তরালে কার্যকর হয় না (এবং কোনও মানক গ্রন্থাগারের জেনারেটর এটি করে না; গোপনে থ্রেডগুলি প্রবর্তন করা ভঙ্গ করা হয়)। yieldপরবর্তী মানটির অনুরোধ না করা পর্যন্ত জেনারেটর প্রতিটি বিরতি দেয় । যদি জেনারেটর I / O কে আবৃত করে রাখে, খুব শীঘ্রই অনুরোধ করা হবে এই ধারণায় OS ওএসটি সক্রিয়ভাবে ফাইল থেকে ডেটা ক্যাশ করছে, তবে এটি ওএস, পাইথন জড়িত নয়।
শ্যাডোএ্যাঞ্জার

90

জেনারেটর ব্যবহারের অন্যতম কারণ হ'ল সমাধানকে কিছু ধরণের সমাধানের জন্য সমাধানকে আরও পরিষ্কার করা।

অন্যটি হ'ল একবারে ফলাফলগুলি চিকিত্সা করা, ফলাফলগুলির বিশাল তালিকাগুলি তৈরি করা এড়িয়ে যাওয়া এড়ানো যে আপনি যেভাবেই বিচ্ছিন্ন প্রক্রিয়া করবেন।

আপনার যদি এইর মতো একটি ফাইবোনাকি-আপ-টু এন ফাংশন থাকে:

# function version
def fibon(n):
    a = b = 1
    result = []
    for i in xrange(n):
        result.append(a)
        a, b = b, a + b
    return result

আপনি আরও সহজেই এটি হিসাবে ফাংশন লিখতে পারেন:

# generator version
def fibon(n):
    a = b = 1
    for i in xrange(n):
        yield a
        a, b = b, a + b

ফাংশন পরিষ্কার হয়। এবং আপনি যদি ফাংশনটি এভাবে ব্যবহার করেন:

for x in fibon(1000000):
    print x,

এই উদাহরণে, যদি জেনারেটর সংস্করণ ব্যবহার করা হয় তবে পুরো 1000000 আইটেম তালিকাটি তৈরি করা হবে না, একবারে কেবল একটি মান। তালিকার সংস্করণটি ব্যবহার করার সময় এমনটি হবে না, যেখানে প্রথমে একটি তালিকা তৈরি করা হবে।


18
এবং যদি আপনার একটি তালিকার দরকার হয় তবে আপনি সর্বদা করতে পারেনlist(fibon(5))
এন্ডোলিথ

41

পিইপি 255 এর "অনুপ্রেরণা" বিভাগটি দেখুন ।

জেনারেটরগুলির একটি অ-স্পষ্ট ব্যবহার বিঘ্নিত ফাংশন তৈরি করছে, যা আপনাকে ইউআই আপডেট করার মতো কাজ করতে দেয় বা থ্রেড ব্যবহার না করার সময় বেশ কয়েকটি কাজ "একযোগে" চালিয়ে দেয় (আসলে ইন্টারলিভড)


1
অনুপ্রেরণা বিভাগটি এর একটি নির্দিষ্ট উদাহরণ সহ চমৎকার: "যখন কোনও উত্পাদকের ফাংশনটিতে যথেষ্ট পরিমাণে কাজ হয় যেটির জন্য উত্পাদিত মানগুলির মধ্যে রাষ্ট্র বজায় রাখা দরকার, বেশিরভাগ প্রোগ্রামিং ভাষাগুলি প্রযোজকের যুক্তিতে কলব্যাক ফাংশন যুক্ত করার বাইরে কোনও আনন্দদায়ক এবং কার্যকর সমাধান দেয় না When তালিকা ... উদাহরণস্বরূপ, স্ট্যান্ডার্ড লাইব্রেরিতে টোকেনাইজ.পি এই পদ্ধতিটি গ্রহণ করে "
বেন ক্র্যাসি

38

আমি এই ব্যাখ্যাটি পেয়েছি যা আমার সন্দেহকে পরিষ্কার করে। কারণ এমন সম্ভাবনা রয়েছে যে ব্যক্তি জানেন Generatorsনা সে সম্পর্কেও জানেন নাyield

প্রত্যাবর্তন

রিটার্নের বিবৃতিটি যেখানে সমস্ত স্থানীয় ভেরিয়েবলগুলি ধ্বংস হয়ে যায় এবং ফলস্বরূপ মানটি কলারকে ফিরে (ফেরত) দেওয়া হয়। যদি একই ফাংশনটি কিছুক্ষণ পরে ডাকা হয় তবে ফাংশনটি ভেরিয়েবলগুলির একটি নতুন নতুন সেট পাবে।

উত্পাদ

কিন্তু যখন আমরা কোনও ফাংশন থেকে বেরিয়ে আসি তখন স্থানীয় ভেরিয়েবলগুলি ফেলে দেওয়া হয় না? এর থেকে বোঝা যায় যে আমরা resume the functionযেখানেই রওনা হয়েছি সেখানেই পারি। এখান থেকেই ধারণাটি generatorsপ্রবর্তন করা হয় এবং বাম yieldযেখানে functionবন্ধ থাকে সেখানে বিবৃতিটি আবার শুরু হয় ।

  def generate_integers(N):
    for i in xrange(N):
    yield i

    In [1]: gen = generate_integers(3)
    In [2]: gen
    <generator object at 0x8117f90>
    In [3]: gen.next()
    0
    In [4]: gen.next()
    1
    In [5]: gen.next()

সুতরাং পাইথন মধ্যে বিবৃতি returnএবং yieldবিবৃতি মধ্যে পার্থক্য ।

ফলন বিবৃতি একটি ফাংশন একটি জেনারেটর ফাংশন করে তোলে।

সুতরাং জেনারেটর পুনরুক্তি তৈরির জন্য একটি সহজ এবং শক্তিশালী সরঞ্জাম। এগুলি নিয়মিত ফাংশনের মতো লেখা হয় তবে তারা yieldযখনই ডেটা ফেরত চায় তারা বিবৃতিটি ব্যবহার করে । পরের বার () বলা হয়ে থাকে, জেনারেটরটি যেখানেই ছেড়ে দিয়েছিল সেগুলি আবার শুরু করে (এটি সমস্ত ডেটা মানগুলিকে মনে করে এবং কোন বিবৃতি সর্বশেষ কার্যকর করা হয়েছিল)।


33

বাস্তব বিশ্বের উদাহরণ

ধরা যাক আপনার মাইএসকিউএল টেবিলটিতে আপনার কাছে 100 মিলিয়ন ডোমেন রয়েছে এবং আপনি প্রতিটি ডোমেনের জন্য আলেক্সা র‌্যাঙ্কটি আপডেট করতে চান।

আপনার প্রথম যেটি দরকার তা হ'ল ডাটাবেস থেকে আপনার ডোমেনের নাম নির্বাচন করা।

ধরা যাক আপনার টেবিলের নাম domainsএবং কলামের নাম domain

আপনি যদি SELECT domain FROM domainsএটি ব্যবহার করেন তবে এটি 100 মিলিয়ন সারিগুলি ফিরিয়ে আনবে যা প্রচুর স্মৃতি গ্রহণ করবে। সুতরাং আপনার সার্ভার ক্রাশ হতে পারে।

সুতরাং আপনি ব্যাচগুলিতে প্রোগ্রামটি চালানোর সিদ্ধান্ত নিয়েছেন। ধরা যাক আমাদের ব্যাচের আকার 1000

আমাদের প্রথম ব্যাচে আমরা প্রথম 1000 টি সারি জিজ্ঞাসা করব, প্রতিটি ডোমেনের জন্য আলেক্সা র‌্যাঙ্কটি পরীক্ষা করব এবং ডাটাবেস সারিটি আপডেট করব।

আমাদের দ্বিতীয় ব্যাচে আমরা পরবর্তী 1000 সারিগুলিতে কাজ করব। আমাদের তৃতীয় ব্যাচে এটি 2001 থেকে 3000 ইত্যাদি হবে।

এখন আমাদের একটি জেনারেটর ফাংশন প্রয়োজন যা আমাদের ব্যাচগুলি উত্পন্ন করে।

আমাদের জেনারেটরের ফাংশনটি এখানে:

def ResultGenerator(cursor, batchsize=1000):
    while True:
        results = cursor.fetchmany(batchsize)
        if not results:
            break
        for result in results:
            yield result

যেমন আপনি দেখতে পাচ্ছেন, আমাদের ফাংশন yieldফলাফলগুলিকে আইএনও রাখে । আপনি যদি এর returnপরিবর্তে কীওয়ার্ডটি ব্যবহার করেন yield, তারপরে ফিরে আসার পরে পুরো ফাংশনটি শেষ হয়ে যায়।

return - returns only once
yield - returns multiple times

যদি কোনও ফাংশন কীওয়ার্ডটি ব্যবহার করে yield তবে এটি জেনারেটর।

এখন আপনি এই মত পুনরাবৃত্তি করতে পারেন:

db = MySQLdb.connect(host="localhost", user="root", passwd="root", db="domains")
cursor = db.cursor()
cursor.execute("SELECT domain FROM domains")
for result in ResultGenerator(cursor):
    doSomethingWith(result)
db.close()

এটি আরও ব্যবহারিক হবে, যদি ফলনটি পুনরাবৃত্ত / ডায়ানমিক প্রোগ্রামিংয়ের ক্ষেত্রে ব্যাখ্যা করা যায়!
igaurav

27

বাফারিং। যখন বড় অংশগুলিতে ডেটা আনার দক্ষ হয় তবে এটি ছোট অংশগুলিতে প্রক্রিয়া করে, তখন কোনও জেনারেটর সহায়তা করতে পারে:

def bufferedFetch():
  while True:
     buffer = getBigChunkOfData()
     # insert some code to break on 'end of data'
     for i in buffer:    
          yield i

উপরেরগুলি আপনাকে প্রক্রিয়াকরণ থেকে সহজেই বাফারিং পৃথক করতে দেয়। গ্রাহক ফাংশন এখন কেবল বাফারিংয়ের চিন্তা না করে একের পর এক মান পেতে পারে।


3
যদি getBigChuckOfData অলস না হয়, তবে আমি এখানে বেনিফিট ফলন বুঝতে পারি না। এই ফাংশনের জন্য ব্যবহারের ক্ষেত্রে কী?
সান জিওফ্রে পিটজ 10'14

1
তবে মুল বক্তব্যটি হ'ল, আইআইইউসি , বাফারফ্যাচটি বিগচানকঅফডেটা কলটি অলসভাবে কাজ করছে। যদি getBigChunkOfData ইতিমধ্যে অলস ছিল, তবে বাফারফ্যাচটি অকেজো হবে। বাফারফ্যাচ () -র প্রতিটি কল একটি বাফার উপাদান ফিরে আসবে, যদিও একটি বিগ চঙ্ক ইতিমধ্যে পড়েছিল And এবং আপনাকে ফিরে আসতে অবশ্যই পরবর্তী উপাদান গণনা করার দরকার নেই, কারণ ফলনটির যান্ত্রিকগুলি কেবল স্পষ্টভাবেই এটি করে।
হামিজাইল

21

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

একটি বিমূর্ত উদাহরণ একটি ফাইবোনাচি নম্বর জেনারেটর হবে যা কোনও লুপের মধ্যে বাস করে না এবং যখনই কোথাও থেকে ফোন করা হয় তখনই পরবর্তী নম্বরটি ক্রমাগত ফিরে আসবে:

def fib():
    first = 0
    second = 1
    yield first
    yield second

    while 1:
        next = first + second
        yield next
        first = second
        second = next

fibgen1 = fib()
fibgen2 = fib()

এখন আপনার কাছে দুটি ফিবোনাচি নম্বর জেনারেটর অবজেক্ট রয়েছে যা আপনি আপনার কোডের যে কোনও জায়গা থেকে কল করতে পারেন এবং তারা সর্বদা বৃহত্তর ফিবোনাচি নম্বরগুলিতে যথাক্রমে ফিরে আসবে:

>>> fibgen1.next(); fibgen1.next(); fibgen1.next(); fibgen1.next()
0
1
1
2
>>> fibgen2.next(); fibgen2.next()
0
1
>>> fibgen1.next(); fibgen1.next()
3
5

জেনারেটরগুলির সম্পর্কে সুন্দর জিনিস হ'ল তারা অবজেক্ট তৈরির হুপের মধ্যে না গিয়ে রাষ্ট্রকে ঘিরে ফেলে। তাদের সম্পর্কে চিন্তা করার একটি উপায় "ফাংশন" যা তাদের অভ্যন্তরীণ অবস্থার কথা মনে করে।

পাইথন জেনারেটরের কাছ থেকে আমি ফিবোনাচি উদাহরণ পেয়েছি - সেগুলি কী? এবং একটু কল্পনা করে আপনি আরও অনেকগুলি পরিস্থিতি নিয়ে আসতে পারেন যেখানে জেনারেটরগুলি forলুপগুলি এবং অন্যান্য traditionalতিহ্যবাহী পুনরাবৃত্তি নির্মাণের দুর্দান্ত বিকল্প তৈরি করে ।


19

সহজ ব্যাখ্যা: একটি forবিবৃতি বিবেচনা করুন

for item in iterable:
   do_stuff()

অনেক সময়, সমস্ত আইটেমের iterableশুরু থেকেই সেখানে থাকা প্রয়োজন হয় না, তবে ফ্লাইতে সেগুলি তৈরি করা যায় যা প্রয়োজন হয়। এটি উভয় ক্ষেত্রে অনেক বেশি দক্ষ হতে পারে

  • স্পেস (আপনার কখনই সমস্ত আইটেম একসাথে সংরক্ষণ করার দরকার নেই) এবং
  • সময় (সমস্ত আইটেমের প্রয়োজন হওয়ার আগে পুনরাবৃত্তি শেষ হতে পারে)।

অন্যান্য সময়, আপনি সমস্ত আইটেম সময় আগে জানেন না। উদাহরণ স্বরূপ:

for command in user_input():
   do_stuff_with(command)

আপনার ব্যবহারকারীর সমস্ত আদেশ আগেই জানার উপায় নেই তবে আপনি যদি জেনারেটর হস্তান্তর করে থাকেন তবে আপনি এই জাতীয় লুপটি ব্যবহার করতে পারেন:

def user_input():
    while True:
        wait_for_command()
        cmd = get_command()
        yield cmd

জেনারেটরের সাহায্যে আপনি অসীম সিকোয়েন্সগুলির মাধ্যমে পুনরাবৃত্তিও করতে পারেন, যা পাত্রে পুনরাবৃত্তি করার সময় অবশ্যই সম্ভব নয়।


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

@ ম্যাট্যাপ: এর itertoolজন্য একটি ব্যবস্থা আছে - দেখুন cycles
মার্টিনো

12

আমার প্রিয় ব্যবহারগুলি হ'ল "ফিল্টার" এবং "কমান" অপারেশন।

ধরা যাক আমরা একটি ফাইল পড়ছি, এবং কেবল "##" দিয়ে শুরু হওয়া লাইনগুলি চাই।

def filter2sharps( aSequence ):
    for l in aSequence:
        if l.startswith("##"):
            yield l

তারপরে আমরা জেনারেটর ফাংশনটি একটি সঠিক লুপে ব্যবহার করতে পারি

source= file( ... )
for line in filter2sharps( source.readlines() ):
    print line
source.close()

হ্রাস উদাহরণ একই রকম। ধরা যাক আমাদের একটি ফাইল আছে যেখানে আমাদের <Location>...</Location>লাইনগুলির ব্লকগুলি সনাক্ত করতে হবে । [এইচটিএমএল ট্যাগ নয়, লাইনগুলি ট্যাগ-জাতীয় দেখার মতো হয়]]

def reduceLocation( aSequence ):
    keep= False
    block= None
    for line in aSequence:
        if line.startswith("</Location"):
            block.append( line )
            yield block
            block= None
            keep= False
        elif line.startsWith("<Location"):
            block= [ line ]
            keep= True
        elif keep:
            block.append( line )
        else:
            pass
    if block is not None:
        yield block # A partial block, icky

আবার আমরা এই জেনারেটরটিকে লুপের জন্য যথাযথভাবে ব্যবহার করতে পারি।

source = file( ... )
for b in reduceLocation( source.readlines() ):
    print b
source.close()

ধারণাটি হ'ল জেনারেটর ফাংশনটি আমাদেরকে একটি সিক্যুয়েন্স ফিল্টার বা হ্রাস করতে দেয়, একই সাথে অন্য সিকোয়েন্সগুলির একটি সময়ে একটি মান দেয়।


8
fileobj.readlines()জেনারেটর ব্যবহারের উদ্দেশ্যকে পরাস্ত করে মেমরির তালিকায় পুরো ফাইলটি পড়বে। যেহেতু ফাইল অবজেক্টগুলি ইতিমধ্যে পুনরাবৃত্তিযোগ্য আপনি তার for b in your_generator(fileobject):পরিবর্তে ব্যবহার করতে পারেন । পুরো ফাইলটি পড়া এড়ানোর জন্য আপনার ফাইলটি একবারে এক লাইনে পড়তে হবে।
nosklo

কমিয়ে দেওয়া লোকেশন বেশ অদ্ভুত একটি তালিকা উপস্থাপন করছে, কেন কেবল প্রতিটি লাইনই উত্পন্ন হয় না? এছাড়াও ফিল্টার এবং হ্রাস প্রত্যাশিত আচরণগুলির সাথে অন্তর্নির্মিত হয় (আইপথনগুলিতে সহায়তা দেখুন ইত্যাদি), আপনার "হ্রাস" এর ব্যবহার ফিল্টার হিসাবে একই।
জেমস অ্যান্টিল

রিডলাইনগুলিতে ভাল পয়েন্ট ()। আমি সাধারণত বুঝতে পারি যে ইউনিট পরীক্ষার সময় ফাইলগুলি প্রথম শ্রেণির লাইন পুনরাবৃত্ত হয়।
এস্লট

প্রকৃতপক্ষে, "হ্রাস" একাধিক স্বতন্ত্র লাইনগুলিকে একটি যৌগিক অবজেক্টে একত্রিত করছে। ঠিক আছে, এটি একটি তালিকা, তবে এটি উত্স থেকে নেওয়া এখনও একটি হ্রাস।
এস্লট

9

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

class Rect():

    def __init__(self, x, y, width, height):
        self.l_top  = (x, y)
        self.r_top  = (x+width, y)
        self.r_bot  = (x+width, y+height)
        self.l_bot  = (x, y+height)

    def __iter__(self):
        yield self.l_top
        yield self.r_top
        yield self.r_bot
        yield self.l_bot

এখন আমি একটি কোণে আয়তক্ষেত্র তৈরি করতে এবং লুপ করতে পারি:

myrect=Rect(50, 50, 100, 100)
for corner in myrect:
    print(corner)

আপনার পরিবর্তে __iter__একটি পদ্ধতি থাকতে পারে iter_cornersএবং এটি দিয়ে কল করতে পারে for corner in myrect.iter_corners()। এটি __iter__তখন থেকেই ব্যবহার করা আরও মার্জিত এবং আমরা ক্লাস উদাহরণের নামটি সরাসরি forঅভিব্যক্তিতে ব্যবহার করতে পারি ।


আমি জেনারেটর হিসাবে একই শ্রেণীর ক্ষেত্রগুলি পাস করার ধারণাটি পছন্দ করেছি
ইউসৌব্রাসিলিও

7

ইনপুট রক্ষণাবেক্ষণের স্থিতিতে পুনরাবৃত্তি করার সময় মূলত কল-ব্যাক ফাংশনগুলি এড়ানো।

জেনারেটর ব্যবহার করে কী করা যায় তার একটি সংক্ষিপ্তসার জন্য এখানে এবং এখানে দেখুন ।


4

কিছু ভাল উত্তর এখানে, তবে আমি পাইথন ফাংশনাল প্রোগ্রামিং টিউটোরিয়ালটি সম্পূর্ণ পড়ার পরামর্শ দিচ্ছি যা জেনারেটরের আরও শক্তিশালী ব্যবহারের ক্ষেত্রে কিছু ব্যাখ্যা করতে সহায়তা করে।


3

যেহেতু জেনারেটরের প্রেরণের পদ্ধতি উল্লেখ করা হয়নি, তাই এখানে একটি উদাহরণ দেওয়া হল:

def test():
    for i in xrange(5):
        val = yield
        print(val)

t = test()

# Proceed to 'yield' statement
next(t)

# Send value to yield
t.send(1)
t.send('2')
t.send([3])

এটি চলমান জেনারেটরে একটি মান প্রেরণের সম্ভাবনাটি দেখায়। নীচের ভিডিওতে জেনারেটর সম্পর্কিত আরও উন্নত কোর্স (সহ)yield সমান্তরাল প্রক্রিয়াকরণের জন্য এক্সপ্লিটেশন, জেনারেটর , পুনরাবৃত্তির সীমা থেকে দূরে থাকা ইত্যাদি)

পাইকন 2014 এ জেনারেটরে ডেভিড বেজলি


2

যখন আমাদের ওয়েব সার্ভার প্রক্সি হিসাবে কাজ করে তখন আমি জেনারেটর ব্যবহার করি:

  1. ক্লায়েন্ট সার্ভার থেকে একটি প্রক্সাইড url অনুরোধ করে
  2. সার্ভারটি লক্ষ্য ইউআরএল লোড করা শুরু করে
  3. সার্ভার ফলাফল পাওয়ার সাথে সাথে ক্লায়েন্টের কাছে ফলাফলটি ফিরিয়ে দেয়

1

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

def primes():
    primes_found = set()
    primes_found.add(2)
    yield 2
    for i in itertools.count(1):
        candidate = i * 2 + 1
        if not all(candidate % prime for prime in primes_found):
            primes_found.add(candidate)
            yield candidate

তারপরে আপনি পরবর্তী প্রাইমগুলির পণ্যগুলি তৈরি করতে এটি ব্যবহার করতে পারেন:

def prime_products():
    primeiter = primes()
    prev = primeiter.next()
    for prime in primeiter:
        yield prime * prev
        prev = prime

এগুলি মোটামুটি তুচ্ছ উদাহরণ, তবে আপনি দেখতে পাচ্ছেন যে এটি বৃহত্তর (সম্ভাব্য অসীম!) ডেটাসেটগুলি আগাম উত্পাদন না করে প্রক্রিয়াজাতকরণের জন্য কীভাবে কার্যকর হতে পারে, যা কেবলমাত্র আরও স্পষ্টতর ব্যবহার।


যদি কোনও না হয় (প্রাইমস_ফাউন্ডে প্রাইম প্রার্থী% প্রাইম) হওয়া উচিত সমস্ত (প্রাইমস_ফাউন্ডে প্রাইম প্রার্থী% প্রাইম)
rjmunro

। হ্যাঁ, আমি লিখতে "কোন (প্রার্থী% মৌলিক == 0 primes_found প্রধান জন্য) যদি ইতি সামান্য, neater যদিও বোঝানো :)।
নিক জনসন

আমার ধারণা আপনি সমস্ত না থাকলে 'না' মুছে ফেলতে ভুলে গেছেন (প্রাইমস_ফাউন্ডে প্রাইম প্রার্থী% প্রাইম)
থাভা

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