পাইথন: জেনারেটর এক্সপ্রেশন মুদ্রণ?


103

পাইথন শেলটিতে, যদি আমি একটি তালিকা বোঝার প্রবেশ করান যেমন:

>>> [x for x in string.letters if x in [y for y in "BigMan on campus"]]

আমি একটি সুন্দর মুদ্রিত ফলাফল পেতে:

['a', 'c', 'g', 'i', 'm', 'n', 'o', 'p', 's', 'u', 'B', 'M']

অভিধান বোঝার জন্য একই:

>>> {x:x*2 for x in range(1,10)}
{1: 2, 2: 4, 3: 6, 4: 8, 5: 10, 6: 12, 7: 14, 8: 16, 9: 18}

আমি যদি কোনও জেনারেটর এক্সপ্রেশন প্রবেশ করি তবে আমি তেমন একটি বন্ধুত্বপূর্ণ প্রতিক্রিয়া পাই না:

>>> (x for x in string.letters if x in (y for y in "BigMan on campus"))
<generator object <genexpr> at 0x1004a0be0>

আমি জানি আমি এটি করতে পারি:

>>> for i in _: print i,
a c g i m n o p s u B M

এর বাইরে (বা কোনও সহায়ক ফাংশন লেখার জন্য) আমি কী সহজেই ইন্টারেক্টিভ শেলের মধ্যে সেই জেনারেটর অবজেক্টটি মূল্যায়ন ও মুদ্রণ করতে পারি?


2
এখানে আসল সমস্যাটা কী? কি মিস করছি?
আন্দ্রেয়াস জং

3
@ পিনেটর: "আসল সমস্যা" কেবলমাত্র generator objectআমি ইন্টারেক্টিভভাবে ইন্টারেক্টিভ প্রম্পটে একটি বোধগম্যতা তৈরি করার সাথে সাথে বিষয়বস্তু মুদ্রণ করতে সক্ষম হতে চাই । কলিং list(_)তা করে। আমি যা করেছি তা তালিকা বোঝার জন্য ব্যবহৃত হয় তারপরে সেগুলি বৃহত্তর কোডে জিনপ্সে পরিণত হয় xp এগুলি চালনার সময়ে এমনভাবে ব্যর্থ হতে পারে যা তালিকার বোঝাপড়াগুলি না করে।
নেকড়ে

5
সংক্ষিপ্ত উত্তরটি হ'ল একটি জেনারেটর এক্সপ্রেশন মুদ্রণ করা যায়নি কারণ এর মানগুলি বিদ্যমান নেই; তারা চাহিদা অনুযায়ী উত্পন্ন হয়। আপনি যা করতে পারেন (ধরে নিচ্ছেন জেনারেটরটি কিছুক্ষণ থামবে) তার থেকে সমস্ত মানগুলি এর মতো করে বেরিয়ে এনে list()মুদ্রণ করুন them
কোস

উত্তর:


161

দ্রুত উত্তর:

এরকম list()জেনারেটরের অভিব্যক্তি কাছাকাছি (প্রায়) ঠিক থাকার সমতূল্য []এটি প্রায় বন্ধনী। হ্যাঁ, আপনি করতে পারেন

>>> list((x for x in string.letters if x in (y for y in "BigMan on campus")))

তবে আপনি ঠিক পাশাপাশি করতে পারেন

>>> [x for x in string.letters if x in (y for y in "BigMan on campus")]

হ্যাঁ, এটি জেনারেটর এক্সপ্রেশনটিকে তালিকা বোধে পরিণত করবে। এটিতে একই জিনিস এবং কলিং তালিকা ()। সুতরাং একটি জেনারেটরকে একটি তালিকার সাথে প্রকাশ করার উপায়টি এর চারপাশে বন্ধনী স্থাপন করা।

বিস্তারিত ব্যাখ্যা:

একটি জেনারেটর এক্সপ্রেশন একটি "নগ্ন" forএক্সপ্রেশন। তাই ভালো:

x*x for x in range(10)

এখন, আপনি নিজেই এটি একটি লাইনে আটকে রাখতে পারবেন না, আপনি একটি বাক্য গঠন ত্রুটি পাবেন। তবে আপনি এটির চারপাশে প্রথম বন্ধনী রাখতে পারেন।

>>> (x*x for x in range(10))
<generator object <genexpr> at 0xb7485464>

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

>>> sorted(x*x for x in range(10))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

মূলত পাইথন 3 এবং পাইথন 2.7 এ উপলব্ধ অন্যান্য সমস্ত বোধগম্যতা একটি জেনারেটর এক্সপ্রেশনকে ঘিরে কেবল সিনট্যাকটিক চিনি। বোধগম্য সেট করুন:

>>> {x*x for x in range(10)}
{0, 1, 4, 81, 64, 9, 16, 49, 25, 36}

>>> set(x*x for x in range(10))
{0, 1, 4, 81, 64, 9, 16, 49, 25, 36}

ডিক্ট বোধগম্যতা:

>>> dict((x, x*x) for x in range(10))
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

>>> {x: x*x for x in range(10)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

এবং পাইথন 3 এর অধীনে উপলব্ধি তালিকাভুক্ত করুন:

>>> list(x*x for x in range(10))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

>>> [x*x for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

পাইথন 2 এর অধীনে, তালিকা বোধগম্যতা কেবল সিনট্যাকটিক চিনি নয়। তবে পার্থক্যটি হ'ল এক্সটি পাইথন 2 এর নিচে নেমস্পেসে ফাঁস হবে।

>>> x
9

পাইথন 3 এর অধীনে আপনি পাবেন

>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined

এর অর্থ হল পাইথনে আপনার জেনারেটর এক্সপ্রেশনটির সামগ্রীটির একটি দুর্দান্ত প্রিন্টআউট পাওয়ার সর্বোত্তম উপায় হ'ল এটির একটি তালিকা বোঝা তৈরি করা! তবে আপনার যদি ইতিমধ্যে জেনারেটরের কোনও জিনিস থাকে তবে এটি অবশ্যই কাজ করবে না। এটি করা কেবল একটি জেনারেটরের একটি তালিকা তৈরি করবে:

>>> foo = (x*x for x in range(10))
>>> [foo]
[<generator object <genexpr> at 0xb7559504>]

সেক্ষেত্রে আপনাকে কল করতে হবে list():

>>> list(foo)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

যদিও এটি কাজ করে তবে মূর্খতাপূর্ণ:

>>> [x for x in foo]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

5
সরকারী শব্দটি "জেনারেটর এক্সপ্রেশন" হিসাবে রয়ে গেছে কারণ "বোঝা" শব্দটি পুনরাবৃত্তি বোঝায়, যা জেন এক্সপ না করে এমন একটি জিনিস যা এই প্রশ্নোত্তরটি সুন্দরভাবে বর্ণনা করেছে :)
ncoghlan

2
list( generator-expression )জেনারেটর এক্সপ্রেশন মুদ্রণ করা হয় না; এটি একটি তালিকা তৈরি করছে (এবং তারপরে একটি ইন্টারেক্টিভ শেলের মধ্যে এটি মুদ্রণ করছে)। পাইথন 3-তে একটি তালিকা তৈরির পরিবর্তে, আপনি জেনারেটর এক্সপ্রেশনটিকে একটি মুদ্রণ বিবৃতিতে ছড়িয়ে দিতে পারেন। বড়) print(*(generator-expression))। এটি কমা ছাড়া এবং শুরুতে এবং শেষে বন্ধনী ছাড়াই উপাদানগুলি মুদ্রণ করে।
এজে নিউফিল্ড

17

একটি তালিকা বা অভিধানের মতো নয়, একটি জেনারেটর অসীম হতে পারে। এটি করা কার্যকর হবে না:

def gen():
    x = 0
    while True:
        yield x
        x += 1
g1 = gen()
list(g1)   # never ends

এছাড়াও, একটি জেনারেটর পড়া এটি পরিবর্তন করে, তাই এটি দেখার কোনও সঠিক উপায় নেই। জেনারেটরের আউটপুট একটি নমুনা দেখতে, আপনি করতে পারেন

g1 = gen()
[g1.next() for i in range(10)]

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

16

আপনি কেবলমাত্র এই কলটিতে এক্সপ্রেশনটি মোড়াতে পারেন list:

>>> list(x for x in string.letters if x in (y for y in "BigMan on campus"))
['a', 'c', 'g', 'i', 'm', 'n', 'o', 'p', 's', 'u', 'B', 'M']

15

বা আপনি mapএকটি মধ্যবর্তী তালিকা তৈরির প্রয়োজন ছাড়াই সর্বদা একজন পুনরাবৃত্তির মাধ্যমে করতে পারেন :

>>> _ = map(sys.stdout.write, (x for x in string.letters if x in (y for y in "BigMan on campus")))
acgimnopsuBM

3
এটিই হ'ল একমাত্র উত্তর যা প্রকৃতপক্ষে বিশাল বস্তু তৈরি না করে জেনারেটরের সামগ্রীগুলি মুদ্রণ করে।
মেরেক আর

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