তালিকা বোধগম্যে ল্যাম্বদা ফাংশন


149

নীচের দুটি তালিকার বোধগম্যর ফলাফল fএবং lambdaফাংশন একই হলেও কেন পৃথক ?

f = lambda x: x*x
[f(x) for x in range(10)]

এবং

[lambda x: x*x for x in range(10)]

আপনি উভয় মনে type(f)এবং type(lambda x: x*x)একই ধরণের ফিরে।


[lambda x: x*x for x in range(10)]এটি প্রথমটির চেয়ে দ্রুততর, যেহেতু এটি বাইরের লুপ ফাংশনটিকে কল করে না, বারবার চ।
রিজা 20'11

@ সেলিনাপ: ... না, পরিবর্তে আপনি লুপের মাধ্যমে প্রতিবার নতুন ফাংশন যুক্ত একটি ব্র্যান্ড তৈরি করছেন। ... এবং এই নতুন ফাংশনটি তৈরি করার ওভারহেড, তারপরে কল করা কিছুটা ধীর হয় (যাইহোক আমার সিস্টেমে)।
Gerrat

@ জিরাট: ওভারহেড থাকা সত্ত্বেও এটি আরও দ্রুত। তবে অবশ্যই [x*x for x in range(10)]এটি আরও ভাল।
রিজা

34
আমি গুগল ফুবার অ্যাক্সেস পেতে সবেমাত্র এখানে প্রবেশ করেছি :)
গাল মার্গালিট

উত্তর:


267

প্রথমটি একটি একক ল্যাম্বদা ফাংশন তৈরি করে এবং তাকে দশবার কল করে।

দ্বিতীয়টি ফাংশনটি কল করে না। এটি 10 ​​টি বিভিন্ন ল্যাম্বদা ফাংশন তৈরি করে। এটি তাদের তালিকায় রাখে। এটিকে আপনার প্রথমটির সমতুল্য করতে:

[(lambda x: x*x)(x) for x in range(10)]

বা আরও ভাল:

[x*x for x in range(10)]

13
বা map(lambda x: x*x, range(10)), সম্ভবত এটিই ছিল প্রথম স্থানে ওপি।
ড্যানিয়েল রোজম্যান

হ্যাঁ, ল্যাম্বদা এক্স: এক্স * এক্স .. (এক্স) টেনিট বলে মনে হচ্ছে।
স্ট্যাটিকর

[ল্যাম্বদা এক্স: এক্স * এক্স রেঞ্জের জন্য (10)] মূলত হাস্কেলের একটি ফান্টচার
মোশে বিরি

@ ড্যানিয়েলরোজম্যান, বা যথাযথভাবে list(map(lambda x: x*x, range(10)))আপনাকে দিতে হবে[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
rrlamichhane

108

এই প্রশ্নটি "বিখ্যাত" এবং "সুস্পষ্ট" পাইথন সিনট্যাক্সের খুব দুর্গন্ধযুক্ত অংশকে স্পর্শ করে - যা অগ্রাধিকার, ল্যাম্বডা বা তালিকা বোধগম্যতার জন্য লাগে।

আমি মনে করি না যে ওপির উদ্দেশ্যটি 0 থেকে 9 পর্যন্ত স্কোয়ারগুলির একটি তালিকা তৈরি করা ছিল যদি এটি হয় তবে আমরা আরও বেশি সমাধান দিতে পারতাম:

squares = []
for x in range(10): squares.append(x*x)
  • এটি হ'ল অপরিহার্য সিনট্যাক্সের ভাল উপায়।

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

সুতরাং, ওপির উপলব্ধি ল্যাম্বডাসের একটি তালিকা ফিরিয়ে দিয়েছে:

[(lambda x: x*x) for x in range(10)]

স্কোয়ারিং ফাংশনের এটি অবশ্যই 10 টি বিভিন্ন অনুলিপি, দেখুন:

>>> [lambda x: x*x for _ in range(3)]
[<function <lambda> at 0x00000000023AD438>, <function <lambda> at 0x00000000023AD4A8>, <function <lambda> at 0x00000000023AD3C8>]

ল্যাম্বডাসের মেমরি ঠিকানাগুলি নোট করুন - এগুলি সমস্ত আলাদা!

আপনার কাছে অবশ্যই এই এক্সপ্রেশনটির আরও "অনুকূল" (হাঃ) সংস্করণ থাকতে পারে:

>>> [lambda x: x*x] * 3
[<function <lambda> at 0x00000000023AD2E8>, <function <lambda> at 0x00000000023AD2E8>, <function <lambda> at 0x00000000023AD2E8>]

দেখা? 3 বার একই লাম্বদা।

দয়া করে মনে রাখবেন, আমি ভেরিয়েবল _হিসাবে ব্যবহার করেছি for। এটা দিয়ে কিছুই করার আছে xlambda(এটা আভিধানিক ঢেকে দিল করা হয়!)। এটা নাও?

আমি আলোচনাটি বাদ দিচ্ছি, সিনট্যাক্সের অগ্রাধিকারটি কেন নয়, এর অর্থ এই:

[lambda x: (x*x for x in range(10))]

যা হতে পারে :,[[0, 1, 4, ..., 81]] বা [(0, 1, 4, ..., 81)], বা যা আমি সবচেয়ে যুক্তিসঙ্গত বলে মনে করি এটিlist 1 টি উপাদানগুলির একটি হতে পারে - generatorমানগুলি ফিরিয়ে দেয়। এটি কেবল ঘটনা নয়, ভাষা এইভাবে কাজ করে না।

তবে কি, যদি ...

আপনি যদি forভেরিয়েবলকে ছায়া না ফেলে এবং এটি আপনার ব্যবহার করে থাকেন তবে কি lambda???

ঠিক আছে, তাহলে বাজে ঘটনা ঘটে। এটা দেখ:

[lambda x: x * i for i in range(4)]

অবশ্যই এই উপায়:

[(lambda x: x * i) for i in range(4)]

তবে এর অর্থ এই নয়:

[(lambda x: x * 0), (lambda x: x * 1), ... (lambda x: x * 3)]

এ তো শুধুই পাগল!

তালিকা অনুধাবন ল্যাম্বডাস এই বোধগম্যতার পরিধি বন্ধ করে দেয়। একটি লেজিকাল ক্লোজার, সুতরাং তারা iরেফারেন্সের মাধ্যমে রেফারেন্স দেয় এবং মূল্যায়ন করার সময় এর মান হয় না!

সুতরাং, এই অভিব্যক্তি:

[(lambda x: x * i) for i in range(4)]

মোটামুটি এর জন্য মূল্যবান:

[(lambda x: x * 3), (lambda x: x * 3), ... (lambda x: x * 3)]

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

এখন, কীভাবে একটি listগুণক ল্যাম্বডাস তৈরি করবেন, যা ক্রমাগত সংখ্যার দ্বারা গুণিত হয়? ঠিক আছে, অনুরূপভাবে গৃহীত উত্তরের মতো, আমাদের iএটির সাথে অন্যকে আবৃত করে সরাসরি টাইটি ভাঙতে হবে lambda, যা তালিকার বোঝাপড়ার এক্সপ্রেশনটির ভিতরে ডাকা হচ্ছে :

আগে:

>>> a = [(lambda x: x * i) for i in (1, 2)]
>>> a[1](1)
2
>>> a[0](1)
2

পরে:

>>> a = [(lambda y: (lambda x: y * x))(i) for i in (1, 2)]
>>> a[1](1)
2
>>> a[0](1)
1

(আমার কাছে বাইরের ল্যাম্বডা ভেরিয়েবলটিও ছিল = i, তবে আমি স্থির করেছি যে এটিই আরও পরিষ্কার সমাধান - আমি yএমনভাবে প্রবর্তন করেছি যাতে আমরা সকলেই দেখতে পাচ্ছি কোন ডাইনটি কোনটি)।

2019-08-30 সম্পাদনা করুন:

@ জোসোলারের একটি পরামর্শ অনুসরণ করে যা @ শেরিড্পের একটি উত্তরে উপস্থিত রয়েছে - তালিকাটি বোঝার "লুপ ভেরিয়েবল" কোনও বস্তুর অভ্যন্তরে "এম্বেড" হতে পারে - সঠিক সময়ে এটি অ্যাক্সেস করার জন্য কীটি রয়েছে। অধ্যায় "পর" অন্য এটা মোড়কে এটা আছে উপরে lambdaএবং এটি অবিলম্বে কলিং বর্তমান মান সঙ্গে i। অন্য উপায় (পড়ার জন্য কিছুটা সহজ - এটি কোনও 'ওয়াট' প্রভাব তৈরি করে না) হ'ল iকোনও partialবস্তুর অভ্যন্তরের মান সংরক্ষণ করা হয় এবং "অভ্যন্তরীণ" (মূল )টিকে lambdaএটি একটি আর্গুমেন্ট হিসাবে গ্রহণ করা হয় ( partialবস্তুটির দ্বারা সরবরাহিত সরবরাহ করে ) কল করার সময়), যেমন:

2 পরে:

>>> from functools import partial
>>> a = [partial(lambda y, x: y * x, i) for i in (1, 2)]
>>> a[0](2), a[1](2)
(2, 4)

দুর্দান্ত, তবে আপনার জন্য এখনও কিছুটা বাঁক আছে! ধরা যাক আমরা কোড রিডারে এটিকে আরও সহজ করে তুলতে চাই না, এবং নামটি দিয়ে ফ্যাক্টরটি পাস করবো (এতে কীওয়ার্ড যুক্তি হিসাবে partial)। আসুন কিছু নামকরণ করা যাক:

2.5 পরে:

>>> a = [partial(lambda coef, x: coef * x, coef=i) for i in (1, 2)]
>>> a[0](1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: <lambda>() got multiple values for argument 'coef'

WAT?

>>> a[0]()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: <lambda>() missing 1 required positional argument: 'x'

অপেক্ষা করুন ... আমরা আর্গুমেন্টের সংখ্যা 1 দ্বারা পরিবর্তন করছি, এবং "খুব বেশি" থেকে "খুব কম" তে যাচ্ছি?

ওয়েল, এটা একটি বাস্তব WAT নয়, যখন আমরা পাস coefকরতে partialএই ভাবে, এটা একটি শব্দ যুক্তি হয়ে তাই এটি অবস্থানগত পরে আসা আবশ্যক x, যুক্তি যেমন:

3 পরে:

>>> a = [partial(lambda x, coef: coef * x, coef=i) for i in (1, 2)]
>>> a[0](2), a[1](2)
(2, 4)

আমি নেস্টেড ল্যাম্বদার চেয়ে শেষ সংস্করণটি পছন্দ করবো তবে প্রতিটি তার নিজস্ব ...


22
এটি একটি নিষ্ঠুর এবং অস্বাভাবিক কাজের সাক্ষাত্কারের প্রশ্ন।
szeitlin

1
যদি আমার সহকর্মী জিজ্ঞাসা না করে, আমি সম্ভবত এই উত্তরটি কখনই অনুসন্ধান করতাম না
piggybox

8
কি দারুন. আমি এই অযৌক্তিক আচরণ দ্বারা খারাপভাবে কামড়েছি। আপনার পোস্টের জন্য আপনাকে ধন্যবাদ!
পিপীলিকা

1
দুর্দান্ত উত্তর। আমি ঠিক এই সমস্যাটিতে দৌড়েছি। একদিকে এটি পাইথন সীমাবদ্ধতার দিকে নির্দেশ করে তবে অন্যদিকে এটি একটি কোড গন্ধ সূচকও হতে পারে। আমি এই খেলনা প্রকল্পের জন্য সমাধানটি ব্যবহার করছি, তবে এটি উত্পাদন পরিবেশে পুনর্গঠনের সিগন্যাল হতে পারে।
আহোটা

2
স্পষ্টতা এবং সম্পূর্ণতার জন্য আপনি সর্বশেষ তালিকাটি বোঝার মতো লিখতে পারেন:[partial(lambda i, x: i * x, i) for i in (1, 2)]
জোসোলার

19

বড় পার্থক্যটি হ'ল প্রথম উদাহরণটি আসলে ল্যাম্বডাকে ডাকে f(x), অন্যদিকে উদাহরণটি দেয় না।

আপনার প্রথম উদাহরণটি সমান [(lambda x: x*x)(x) for x in range(10)]যখন আপনার দ্বিতীয় উদাহরণটি সমান [f for x in range(10)]


11

প্রথমটি

f = lambda x: x*x
[f(x) for x in range(10)]

f()রেঞ্জের প্রতিটি মানের জন্য চলে তাই এটি f(x)প্রতিটি মানের জন্য হয়

দ্বিতীয়টি

[lambda x: x*x for x in range(10)]

তালিকার প্রতিটি মানের জন্য ল্যাম্বদা চালায় তাই এটি সমস্ত ফাংশন তৈরি করে।


11

মানুষ ভাল উত্তর দিয়েছেন কিন্তু আমার মতে সবচেয়ে গুরুত্বপূর্ণ অংশ উল্লেখ করতে ভুলে গেছি: দ্বিতীয় উদাহরণে Xতালিকা ধী হিসাবে একই নয় Xএর lambdaফাংশন, তারা সম্পূর্ণভাবে সম্পর্কহীন হয়। সুতরাং দ্বিতীয় উদাহরণটি আসলে একই রকম:

[Lambda X: X*X for I in range(10)]

অভ্যন্তরীণ পুনরাবৃত্তি range(10)কেবলমাত্র তালিকায় 10 টি একই রকম ল্যাম্বডা ফাংশন তৈরি করার জন্য দায়ী (10 পৃথক ফাংশন তবে সম্পূর্ণ অনুরূপ - প্রতিটি ইনপুটটির পাওয়ার 2 ফেরৎ)।

অন্যদিকে, প্রথম উদাহরণটি সম্পূর্ণ আলাদা কাজ করে, কারণ পুনরাবৃত্তির এক্সটি ফলাফলের সাথে ইন্টারঅ্যাক্ট করে না, প্রতিটি পুনরাবৃত্তির জন্য মান X*Xতাই ফলাফল হয়[0,1,4,9,16,25, 36, 49, 64 ,81]


এটি একটি গুরুত্বপূর্ণ পয়েন্ট। আমি আপনাকে উত্সাহিত করেছি এবং আমার উত্তরে এটি বিশদভাবে জানিয়েছি।
টমাসজ গ্যান্ডার

6

অন্যান্য উত্তর সঠিক হয়, কিন্তু আপনি যদি ফাংশন একটি তালিকা তৈরি করার চেষ্টা করছেন, একটি ভিন্ন প্যারামিটার, যে মৃত্যুদন্ড কার্যকর করা যেতে পারে সঙ্গে প্রতিটি পরে , নিম্নলিখিত কোড যা যা করবেন:

import functools
a = [functools.partial(lambda x: x*x, x) for x in range(10)]

b = []
for i in a:
    b.append(i())

In [26]: b
Out[26]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

উদাহরণটি সহীহরূপে থাকা অবস্থায়, আমি দরকারী হয়েছি যখন আমি ফাংশনগুলির একটি তালিকা চেয়েছিলাম যা প্রত্যেকটি আলাদা আলাদা কিছু মুদ্রণ করে ie

import functools
a = [functools.partial(lambda x: print(x), x) for x in range(10)]

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