কোনটি ব্যবহার করার চেয়ে বেশি পছন্দনীয়: ল্যাম্বডা ফাংশন বা নেস্টেড ফাংশন ('ডিএফ')?


105

আমি বেশিরভাগ ল্যাম্বদা ফাংশন ব্যবহার করি তবে কখনও কখনও নেস্টেড ফাংশন ব্যবহার করি যা মনে হয় একই আচরণ করে।

এখানে কিছু তুচ্ছ উদাহরণ রয়েছে যেখানে তারা অন্য কোনও ফাংশনের মধ্যে যদি পাওয়া যায় তবে তারা কার্যকরভাবে একই কাজ করে:

লাম্বদা ফাংশন

>>> a = lambda x : 1 + x
>>> a(5)
6

নেস্টেড ফাংশন

>>> def b(x): return 1 + x

>>> b(5)
6

একে অপরকে ব্যবহার করার সুবিধা কি? (পারফরম্যান্স? পঠনযোগ্যতা? সীমাবদ্ধতা? ধারাবাহিকতা? ইত্যাদি)

এটা কি কোন ব্যাপার? যদি তা না হয় তবে এটি পাইথোনিক নীতি লঙ্ঘন করে:

এটি করার জন্য একটি — এবং অগ্রাধিকার কেবল একটিই — সুস্পষ্ট উপায় থাকতে হবে

উত্তর:


110

যদি আপনাকে lambdaকোনও নাম নির্ধারণ করতে হয় তবে defতার পরিবর্তে একটি ব্যবহার করুন। defগুলি কেবল একটি অ্যাসাইনমেন্টের জন্য সিনট্যাকটিক চিনি, ফলস্বরূপ একই হয়, এবং তারা অনেক বেশি নমনীয় এবং পঠনযোগ্য।

lambdas একবার ব্যবহারের জন্য ব্যবহার করা যেতে পারে , ফাংশন ফেলে দিন যার নাম থাকবে না।

তবে, এই ব্যবহারের ক্ষেত্রে খুব বিরল। আপনাকে নামহীন ফাংশন অবজেক্টগুলি খুব কমই পাস করতে হবে।

বিল্টিনগুলি map()এবং filter()প্রয়োজনীয় ফাংশন অবজেক্টগুলির প্রয়োজন, তবে তালিকাটি উপলব্ধি এবং জেনারেটর এক্সপ্রেশনগুলি সাধারণত সেই ফাংশনগুলির চেয়ে বেশি পঠনযোগ্য ছাড়াই সমস্ত ব্যবহারের কেসগুলি কভার করতে পারে।

ক্ষেত্রে আপনার সত্যিকার অর্থে একটি ছোট ফাংশন অবজেক্ট প্রয়োজন, আপনার পরিবর্তে operatorমডিউল ফাংশন ব্যবহার করা উচিতoperator.addlambda x, y: x + y

আপনার যদি এখনও কিছু lambdaআবৃত না প্রয়োজন হয় তবে আপনি সম্ভবত defআরও পড়ার জন্য একটি লিখতে বিবেচনা করতে পারেন । যদি ফাংশনটি operatorমডিউলটির তুলনায় আরও জটিল defহয় তবে সম্ভবত এটি আরও ভাল।

সুতরাং, বাস্তব বিশ্বের ভাল lambdaব্যবহারের ক্ষেত্রে খুব বিরল।


12
আমি কখন ব্যবহার করব তার উত্তরের সাথে আমি একমত lambda, তবে আমি একমত নই যে এটি "খুব বিরল", মূল ফাংশন sortedবা itertools.groupbyইত্যাদির জন্য এটি সাধারণ বিষয় , যেমনsorted(['a1', 'b0'], key= lambda x: int(x[1]))
ক্রিস_আরান্ডস

31

ব্যবহারিকভাবে বলতে গেলে আমার কাছে দুটি পার্থক্য রয়েছে:

প্রথমটি হচ্ছে তারা কী করে এবং তারা কী ফিরিয়ে দেয়:

  • ডিএফ এমন একটি কীওয়ার্ড যা কোনও কিছুই ফেরত না এবং স্থানীয় নেমস্পেসে একটি 'নাম' তৈরি করে।

  • ল্যাম্বদা এমন একটি কীওয়ার্ড যা কোনও ফাংশন অবজেক্ট দেয় এবং স্থানীয় নেমস্পেসে একটি 'নাম' তৈরি করে না।

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

কিছু ফ্রেমওয়ার্কে এটি আসলে বেশ সাধারণ; উদাহরণস্বরূপ, আমি প্রচুর পরিমাণে টুইস্ট ব্যবহার করি এবং এরকম কিছু করে

d.addCallback(lambda result: setattr(self, _someVariable, result))

বেশ সাধারণ এবং ল্যাম্বডাসের সাথে আরও সংক্ষিপ্ত।

দ্বিতীয় পার্থক্যটি হ'ল আসল ফাংশনটি কী করার অনুমতি দেয় about

  • 'ডিফ' দিয়ে সংজ্ঞায়িত কোনও ফাংশনে কোনও পাইথন কোড থাকতে পারে
  • 'ল্যাম্বদা' দিয়ে সংজ্ঞায়িত একটি ফাংশনটির একটি এক্সপ্রেশনকে মূল্যায়ন করতে হয় এবং এতে মুদ্রণ, আমদানি, উত্থাপন, ... এর মতো বিবৃতি থাকতে পারে না ...

উদাহরণ স্বরূপ,

def p(x): print x

প্রত্যাশিত হিসাবে কাজ করে, যখন

lambda x: print x

একটি সিনট্যাক্সেরর।

অবশ্যই, সেখানে কর্মক্ষেত্র রয়েছে - বিকল্প printসহ sys.stdout.writeবা এর importসাথে __import__। তবে সাধারণত আপনি এক্ষেত্রে কোনও ফাংশন নিয়ে যাওয়াই ভাল।


23

এই সাক্ষাত্কারে, গিডো ভ্যান রসুম বলেছেন যে তিনি চান তিনি 'ল্যাম্বডা' কে পাইথনে প্রবেশ করতে দিতেন না:

" প্র। পাইথনের কোন বৈশিষ্ট্যটি নিয়ে আপনি কমপক্ষে সন্তুষ্ট? বাস্তবে, এটি ভালভাবে পরিণত হয়নি Py পাইথনের কেবল দুটি স্কোপ রয়েছে: স্থানীয় এবং বৈশ্বিক This এটি ল্যাম্বডা ফাংশনকে বেদনাদায়ক করে তোলে কারণ আপনি প্রায়শই ভেরিয়েবলগুলি অ্যাক্সেস করতে চান ল্যাম্বডাটি যে স্কোপটি সংজ্ঞায়িত করা হয়েছিল, তবে আপনি দুটি স্কোপগুলির কারণে পারবেন না this এটির চারপাশে একটি উপায় রয়েছে তবে এটি একটি পাদদেশের কিছু Often প্রায়শই পাইথনের সাথে গোলমাল করার পরিবর্তে কেবল লুপের জন্য ব্যবহার করা আরও সহজ বলে মনে হয় ল্যাম্বদা ফাংশন: মানচিত্র এবং বন্ধুরা কেবল তখনই ভাল কাজ করে যখন ইতিমধ্যে কোনও বিল্ট-ইন ফাংশন রয়েছে যা আপনি যা চান তা করেন।

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

আইএমএইচও, ইম্বডাস কখনও কখনও সুবিধাজনক হতে পারে তবে সাধারণত পাঠযোগ্যতার ব্যয়ে সুবিধাজনক। আপনি কি আমাকে বলতে পারেন এটি কি করে:

str(reduce(lambda x,y:x+y,map(lambda x:x**x,range(1,1001))))[-10:]

আমি এটি লিখেছিলাম এবং এটি বের করতে আমার এক মিনিট সময় লেগেছে। এটি প্রোজেক্ট অলারের - এটি আমি বলব না কোন সমস্যাটি আমি ঘৃণাকারীদের ঘৃণা করি তবে এটি 0.124 সেকেন্ডে চলে :)


20
মনে রাখবেন যে সাক্ষাত্কারটি বরং পুরানো, এবং পাইথন দীর্ঘকাল ধরে নেস্টেড স্কোপগুলি যুক্ত করেছেন, যা ল্যাম্বদার বিরুদ্ধে তিনি যে যুক্তি দিয়েছিলেন তা আর প্রাসঙ্গিক করে তোলে। আমি নিশ্চিত যে তিনি এখনও ল্যাম্বডাকে অনুশোচনা করছেন, তবে পাইথন ৩.০ এ এটি সরাতে যথেষ্ট নয়।
থমাস ওয়াউটারস

10
সত্যিই আপনার উদাহরণটি ল্যাম্বডাস নয়, ওয়ান-লাইনারের বিরুদ্ধে যুক্তি হওয়া উচিত। এছাড়াও, আপনার ল্যাম্বডা: আর্ট (যোগফল (মানচিত্র (ল্যাম্বডা এক্স: এক্স ** এক্স, রেঞ্জ (1001)))) হ্রাস করার পরিবর্তে বিল্ট-ইন সাম ফাংশনটি ব্যবহার করা উচিত ছিল: [: - 10]
ট্রিপটিচ

4
@ থমাসওয়াটার্স: আমি বুঝতে পেরেছি যে 3.0.০-তে lambdaসরানো না হওয়া একটি কাছের জিনিস এবং গুইডো এটি বজায় রাখতে লড়াই করছে না।
ইথান ফুরম্যান

11

এন = 1000 এর জন্য ল্যাম্বদা বনাম কোনও ফাংশন কল করার কিছু সময়সীমা এখানে রয়েছে:

In [11]: def f(a, b):
             return a * b

In [12]: g = lambda x, y: x * y

In [13]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    f(a, b)
   ....:
100 loops, best of 3: 285 ms per loop

In [14]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    g(a, b)
   ....:
100 loops, best of 3: 298 ms per loop

In [15]: %%timeit -n 100
for a in xrange(n):
  for b in xrange(n):
    (lambda x, y: x * y)(a, b)
   ....:
100 loops, best of 3: 462 ms per loop

4
ল্যাম্বদা এবং সংজ্ঞায়িত সংস্করণগুলি প্রায় সমতুল্য তা দেখতে আকর্ষণীয়। শেষ পরীক্ষাটি আরও সময় নিয়েছিল কারণ অজগরকে সম্ভবত বার বার জায়গা বরাদ্দ করা দরকার যখন এটি ল্যাম্বদা ফাংশনটি সংজ্ঞায়িত করে।
hlin117

আমি অনুমান করি যে এটি সংজ্ঞাটি স্থানীয় ভেরিয়েবলগুলি উল্লেখ করতে পারে (যা পরিবর্তিত হতে পারে) ... যদিও এটি ক্ষেত্রে যেমন এটি হয় না, এখানে যেমন সিপিথন আরও ভাল কাজ করতে পারে।
অ্যান্ডি হেডেন

ডিস.ডিস ব্যবহার করুন; আপনার (ল্যাম্বদা এক্স, y: x * y) প্রতিটি লুপটি ফাংশন তৈরি করে। যদি আপনি লুপটির আগে ল্যাম্বডা তৈরি করেন (ওরফে এফ = ল্যাম্বদা এক্স, y: x * y), ফাংশনটি কল করার জন্য বাইটকোডটি আপনার পূর্ববর্তী উদাহরণে জি / এফের মতো একই হবে, সুতরাং ল্যাম্বডা কার্যকারিতা একই একটি ডিএফ ফাংশন হিসাবে। সুতরাং ল্যাম্বদা বা ডিএফ কোনও প্রভাব হিসাবে যদি আপনি এটি একই ব্যবহার করেন। বিপরীত কি, লুপ মধ্যে চ () ফাংশন ডিক্লেয়ার, তাহলে এটি কল ...
টিটো

@ টিটো আমি বিশ্বাস করি যে এটি 3 সময়কালের উদাহরণগুলি ঠিক তা-ও দেখিয়েছে ...
অ্যান্ডি হেডেন

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

7

কর্মক্ষমতা:

সঙ্গে একটি ফাংশন তৈরি করা হচ্ছে lambdaহল সামান্য দ্রুত সঙ্গে এটি তৈরি চেয়ে defdefস্থানীয়দের টেবিলে একটি নাম এন্ট্রি তৈরি করার কারণে পার্থক্য is ফলস্বরূপ ফাংশনটিতে একই মৃত্যুদন্ড কার্যকর করার গতি রয়েছে।


পঠনযোগ্যতা:

বেশিরভাগ পাইথন ব্যবহারকারীদের জন্য লাম্বদা ফাংশনগুলি কিছুটা কম পঠনযোগ্য তবে কিছু পরিস্থিতিতে আরও বেশি সংক্ষিপ্ত। অ-কার্যকরী থেকে কার্যকরী রুটিনে রূপান্তর বিবেচনা করুন:

# Using non-functional version.

heading(math.sqrt(v.x * v.x + v.y * v.y), math.atan(v.y / v.x))

# Using lambda with functional version.

fheading(v, lambda v: math.sqrt(v.x * v.x + v.y * v.y), lambda v: math.atan(v.y / v.x))

# Using def with functional version.

def size(v):
    return math.sqrt(v.x * v.x + v.y * v.y)

def direction(v):
    return math.atan(v.y / v.x)

deal_with_headings(v, size, direction)

আপনি দেখতে পাচ্ছেন যে lambdaসংস্করণটি সংক্ষিপ্ত এবং "সহজ" এই অর্থে যে lambda v:কার্যকরী সংস্করণে রূপান্তর করতে আপনার কেবল মূল অ-কার্যকরী সংস্করণে যুক্ত করতে হবে। এটি আরও অনেক সংক্ষিপ্ত। তবে মনে রাখবেন, পাইথন ব্যবহারকারী প্রচুর পরিমাণে ল্যাম্বডা সিনট্যাক্স দ্বারা বিভ্রান্ত হয়ে পড়বেন, তাই আপনি যা দৈর্ঘ্যে এবং বাস্তব জটিলতায় হারাবেন তা সহকর্মীদের কাছ থেকে বিভ্রান্তিতে ফিরে আসতে পারে।


সীমাবদ্ধতা:

  • lambda ভেরিয়েবলের নাম নির্ধারিত না করে কেবলমাত্র একবারে ফাংশন ব্যবহার করা যেতে পারে।
  • lambdaচলক নামগুলিতে নির্ধারিত ফাংশনগুলির কার্যকারণের চেয়ে কোনও সুবিধা নেই def
  • lambda ফাংশনগুলি আচার করা কঠিন বা অসম্ভব হতে পারে।
  • def যুক্তিসঙ্গত বর্ণনামূলক এবং অনন্য বা স্কোমে অন্তত অন্যথায় অব্যবহৃত হওয়ার জন্য ফাংশনগুলির নাম অবশ্যই সাবধানতার সাথে বেছে নেওয়া উচিত।

ধারাবাহিকতা:

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


পূর্ব বিদ্যমান ফাংশন:

যেমনটি অন্যদের দ্বারা উল্লিখিত হয়েছে, ক্ষেত্রের অনেকগুলি ব্যবহারগুলি মডিউল বা অন্যান্য মডিউলগুলির lambdaদ্বারা প্রতিস্থাপন করা যেতে পারে operator। এই ক্ষেত্রে:

do_something(x, y, lambda x, y: x + y)
do_something(x, y, operator.add)

প্রাক বিদ্যমান বিদ্যমান ফাংশন ব্যবহার কোড অনেক ক্ষেত্রে কোডকে আরও পঠনযোগ্য করে তুলতে পারে।


পাইথোনিক নীতি: "এটির জন্য একমাত্র fe এবং পছন্দসই একমাত্র — সুস্পষ্ট উপায় থাকা উচিত"

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

[e for e in some_array if some_condition(e)]
filter(some_array, some_condition)

lambdaএবং defএকই।

এটি মতামতের বিষয়, তবে আমি বলব যে পাইথন ভাষার সাধারণ ব্যবহারের উদ্দেশ্যে যা কিছু রয়েছে যা স্পষ্টতই কোনও কিছু ভাঙ্গেনি "পাইথোনিক" যথেষ্ট।


7

আরও বেশি পছন্দনীয়: ল্যাম্বদা ফাংশন বা নেস্টেড ফাংশনগুলি ( def)?

নিয়মিত ফাংশন ব্যবহার করে ল্যাম্বডা ব্যবহার করার একটি সুবিধা রয়েছে: এগুলি একটি এক্সপ্রেশনে তৈরি করা হয়।

বেশ কয়েকটি ত্রুটি রয়েছে:

  • নাম নেই (শুধু '<lambda>')
  • কোনও ডকাস্ট্রিং নেই
  • কোনও টিকা নেই
  • কোন জটিল বিবৃতি

তারা উভয় একই ধরণের বস্তু। এই কারণে, আমি সাধারণত defল্যাম্বডাসের পরিবর্তে কীওয়ার্ড দিয়ে ফাংশন তৈরি করতে পছন্দ করি ।

প্রথম পয়েন্ট - তারা একই ধরণের অবজেক্ট

একটি ল্যাম্বডা নিয়মিত ফাংশন হিসাবে একই ধরণের অবজেক্টের ফলস্বরূপ

>>> l = lambda: 0
>>> type(l)
<class 'function'>
>>> def foo(): return 0
... 
>>> type(foo)
<class 'function'>
>>> type(foo) is type(l)
True

যেহেতু ল্যাম্বডাস ফাংশন, তারা প্রথম শ্রেণীর বস্তু।

উভয় ল্যাম্বডাস এবং ফাংশন:

  • আর্গুমেন্ট হিসাবে হিসাবে পাস করা যেতে পারে (নিয়মিত ফাংশন হিসাবে একই)
  • যখন বাইরের ফাংশনের মধ্যে তৈরি হয় তখন বাহ্যিক ফাংশনগুলির স্থানীয়দের উপর এটি বন্ধ হয়ে যায়

কিন্তু ল্যাম্বডাস হ'ল ডিফল্টরূপে, এমন কিছু জিনিস হারিয়েছে যা ফাংশনগুলি সম্পূর্ণ ফাংশন সংজ্ঞা সিনট্যাক্সের মাধ্যমে পায়।

একটি লাম্বা __name__হয়'<lambda>'

লাম্বদাস অজানা ফাংশন, সর্বোপরি, তাই তারা নিজের নাম জানেন না।

>>> l.__name__
'<lambda>'
>>> foo.__name__
'foo'

সুতরাং ল্যাম্বডা তাদের নামস্থানে প্রোগ্রামগতভাবে দেখা যাবে না।

এটি নির্দিষ্ট কিছু জিনিস সীমাবদ্ধ করে। উদাহরণস্বরূপ, fooসিরিয়ালযুক্ত কোড সহ সন্ধান করা যেতে পারে, যখন lনা পারে:

>>> import pickle
>>> pickle.loads(pickle.dumps(l))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
_pickle.PicklingError: Can't pickle <function <lambda> at 0x7fbbc0464e18>: 
attribute lookup <lambda> on __main__ failed

আমরা fooঠিক দেখতে পারি - কারণ এটি নিজের নামটি জানে:

>>> pickle.loads(pickle.dumps(foo))
<function foo at 0x7fbbbee79268>

ল্যাম্বডাসের কোনও টিকা নেই এবং কোনও ডাস্ট্রিং নেই

মূলত, ল্যাম্বডাস নথিভুক্ত হয় না। fooআরও নথিভুক্ত হতে পুনরায় লিখুন :

def foo() -> int:
    """a nullary function, returns 0 every time"""
    return 0

এখন, foo এর ডকুমেন্টেশন রয়েছে:

>>> foo.__annotations__
{'return': <class 'int'>}
>>> help(foo)
Help on function foo in module __main__:

foo() -> int
    a nullary function, returns 0 every time

যদিও ল্যাম্বডাসকে একই তথ্য দেওয়ার মতো ব্যবস্থা আমাদের নেই:

>>> help(l)
Help on function <lambda> in module __main__:

<lambda> lambda (...)

তবে আমরা এগুলিকে হ্যাক করতে পারি:

>>> l.__doc__ = 'nullary -> 0'
>>> l.__annotations__ = {'return': int}
>>> help(l)
Help on function <lambda> in module __main__:

<lambda> lambda ) -> in
    nullary -> 0

তবে সাহায্যের আউটপুট জগাখিচুড়ি করতে গিয়ে কিছু সমস্যা আছে probably

লাম্বদাস কেবল একটি অভিব্যক্তি ফিরিয়ে দিতে পারে

লাম্বদাস জটিল বিবৃতি, কেবলমাত্র প্রকাশের পক্ষে ফিরে আসতে পারে না।

>>> lambda: if True: 0
  File "<stdin>", line 1
    lambda: if True: 0
             ^
SyntaxError: invalid syntax

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

আমরা স্পষ্টতা এবং রক্ষণাবেক্ষণের জন্য পাইথন ব্যবহার করি। ল্যাম্বডাসের অতিরিক্ত ব্যবহার তার বিরুদ্ধে কাজ করতে পারে।

শুধুমাত্র lambdas জন্য গোলমালে: একটি একক এক্সপ্রেশনে তৈরি করা যেতে পারে

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

কোনও ফাংশন কলের অভ্যন্তরে একটি ফাংশন তৈরি করা (সস্তার) নামের অনুসন্ধান বনাম অন্য কোথাও তৈরি হওয়া এড়িয়ে চলে।

তবে পাইথন যেহেতু কঠোরভাবে মূল্যায়ন করা হয়েছে, নাম অনুসন্ধান এড়ানো বাদ দিয়ে অন্য কোনও কর্মক্ষমতা অর্জন করতে পারে না।

খুব সাধারণ অভিব্যক্তির জন্য, আমি একটি ল্যাম্বডা বেছে নিতে পারি।

আমি ইন্টারেক্টিভ পাইথন করার সময় ল্যাম্বডাস ব্যবহার করার ঝোঁক রাখি, যখন কেউ কখন করবে তখন একাধিক লাইন এড়াতে। আমি যখন কল করার সময় কোনও কনস্ট্রাক্টরের সাথে যুক্তিতে পাস করতে চাই তখন আমি নিম্নলিখিত ধরণের কোড ফর্ম্যাটটি ব্যবহার করি timeit.repeat:

import timeit

def return_nullary_lambda(return_value=0):
    return lambda: return_value

def return_nullary_function(return_value=0):
    def nullary_fn():
        return return_value
    return nullary_fn

এবং এখন:

>>> min(timeit.repeat(lambda: return_nullary_lambda(1)))
0.24312214995734394
>>> min(timeit.repeat(lambda: return_nullary_function(1)))
0.24894469301216304

আমি বিশ্বাস করি উপরের সামান্য সময়ের পার্থক্যটি নাম অনুসন্ধানের জন্য দায়ী করা যেতে পারে return_nullary_function- মনে রাখবেন যে এটি খুব নগন্য।

উপসংহার

লাম্বডাস অনানুষ্ঠানিক পরিস্থিতিতে যেখানে আপনি একক দৃষ্টিকোণ করার পক্ষে কোডের লাইনকে ন্যূনতম করতে চান সেখানে ভাল।

ল্যাম্বডাস আরও আনুষ্ঠানিক পরিস্থিতিতে খারাপ যেখানে আপনার কোডগুলির সম্পাদকদের যারা পরে আসবেন তাদের স্পষ্টতা দরকার, বিশেষত ক্ষেত্রে যেখানে তারা অ-তুচ্ছ হয়।

আমরা জানি আমাদের জিনিসগুলিকে ভাল নাম দেওয়ার কথা রয়েছে। যখন বস্তুর হয়েছে কীভাবে আমরা তা করতে পারেন কোন নাম?

এই সমস্ত কারণে, আমি সাধারণত এর defপরিবর্তে ফাংশন তৈরি করতে পছন্দ করি lambda


6

আমি নসক্লোর পরামর্শের সাথে একমত: আপনার যদি ফাংশনটির একটি নাম দেওয়ার দরকার হয় তবে ব্যবহার করুন def। আমি lambdaকেবলমাত্র অন্য ফাংশনে কোডের একটি সংক্ষিপ্ত স্নিপেট দিচ্ছি এমন ক্ষেত্রে আমি ফাংশনগুলি সংরক্ষণ করি

a = [ (1,2), (3,4), (5,6) ]
b = map( lambda x: x[0]+x[1], a )

4
মানচিত্র / ল্যাম্বদা বেশিরভাগ সংমিশ্রণে, আপনি এটি তালিকা বোধ বা আরও উপযুক্ত ফাংশন দিয়ে প্রতিস্থাপন করতে পারেন। উদাহরণস্বরূপ, "মানচিত্র (যোগফল, ক)" বা "[এক্স [0] + এক্স [1] এক্স এর জন্য এক্স]]"
জন মিলিকিন

হ্যা, এটা সত্য. যদিও আমি কখনও কখনও মানচিত্র পছন্দ করি ()। এটি বেশিরভাগই ইন-লাইন ফাংশনটি ব্যবহারের একটি স্বতন্ত্র উদাহরণ।
ড্যান লেন্সকি 20

ঠিক ... বেশিরভাগ উদাহরণগুলি বোঝা যায়, কারণ এটি ব্যবহার করা অপ্রাকৃত এবং বেশিরভাগ ক্ষেত্রে ব্যবহারিক আরও ভাল উপায় রয়েছে।
nosklo

5

অন্যান্য উত্তরের সাথে একমত হওয়ার সময়, কখনও কখনও এটি আরও পাঠযোগ্য। lambdaউপকারে আসে এমন একটি উদাহরণ এখানে , ব্যবহারের ক্ষেত্রে আমি একটি এন ডাইমেনশনাল এর মুখোমুখি রাখি defaultdict
এখানে একটি উদাহরণ:

from collections import defaultdict
d = defaultdict(lambda: defaultdict(list))
d['Foo']['Bar'].append(something)

আমি এটি defদ্বিতীয় মাত্রার জন্য তৈরি করার চেয়ে বেশি পঠনযোগ্য বলে মনে করি । এটি উচ্চ মাত্রার জন্য আরও বেশি তাৎপর্যপূর্ণ।


from functools import partial; defaultdict(partial(defaultdict, list))। আপনি যদি একবারে একাধিকবার ব্যবহার করতে চান তবে কোনও নামের জন্য আংশিক বরাদ্দ করুন। কিন্তু, যদি আপনি রাখতে এই কনস্ট্রাক্ট সম্মুখীন উপর, এটা মানে আপনি শুষ্ক হয় না। এটি একটি ইউটিলিটি লাইব্রেরিতে ফ্যাক্টর করুন। আপনি এই কনস্ট্রাক্টটি অন্য ফান্টুলগুলি (বা একটি লুপ বা পুনরাবৃত্তি) ব্যবহার করে একটি সালিসি এন-ডাইমেনশনাল ডিফল্টডিক্ট তৈরি করতে ব্যবহার করতে পারেন।
ডিলান ইয়ং

3

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

x = [f for f in range(1, 40) if f % 2]

প্রতিদিনের ব্যবহারে ল্যাম্বডা ব্যবহারের জন্য বাস্তব ঘটনাটি কল্পনা করা শক্ত hard ফলস্বরূপ, আমি বলব, ল্যাম্বদা এড়িয়ে চলুন এবং নেস্টেড ফাংশনগুলি তৈরি করুন।


3

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

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

সম্পাদনা: এটি একটি পুরানো প্রশ্ন এবং বিষয়টি সম্পর্কে আমার মতামত কিছুটা বদলে গেছে।

প্রথমত, আমি lambdaভেরিয়েবলের কাছে একটি এক্সপ্রেশন নির্ধারণের বিরুদ্ধে দৃ strongly়ভাবে পক্ষপাতিত্ব করি ; যেহেতু অজগরটির একটি নির্দিষ্ট বাক্য গঠন রয়েছে কেবল (ইঙ্গিত, def) এর জন্য। এগুলি ছাড়াও, ল্যাম্বদা ব্যবহারের অনেকগুলি, এমনকি যখন তারা একটি নাম না পেয়েও পূর্বনির্ধারিত (এবং আরও দক্ষ) বাস্তবায়ন করে থাকে। উদাহরণস্বরূপ, প্রশ্নের উদাহরণটি সংক্ষিপ্তভাবে সংক্ষিপ্ত হতে পারে (1).__add__, এটি একটি lambdaবা এর মধ্যে মোড়ানোর প্রয়োজন ছাড়াই def। অন্যান্য অনেকগুলি সাধারণ ব্যবহার operator, itertoolsএবং functoolsমডিউলগুলির কিছু সংমিশ্রণে সন্তুষ্ট হতে পারে ।


4
(1).__add__- ডানার পদ্ধতি সরাসরি কল করা কখনই ঘটে না। lambdaপ্রত্যক্ষ ডেনার কলের জন্য এক হাজার এস।
ইথান ফুরম্যান

4
@ ইথানফর্মান: ঠিক আছে, আমার অভিজ্ঞতায় প্রকৃতির কলগুলি (1).__add__কিছুটা অস্বাভাবিক, তবে আমি "উচিত" এর কাছাকাছি যেতে চাই না। সন্দেহ নেই, আমি প্রাক্তনটি আরও বেশি পাঠযোগ্য বলে মনে করি lambda x: 1 + x। যদি আমাদের কাছে হ্যাসেলস স্লাইস স্বরলিপি তুলনায় আরও কিছু অনুরূপ থাকে (1+)তবে তা দুর্দান্ত হতে পারে তবে শব্দার্থের ঠিক কী জিনিসটি আমাদের তা করতে হবে, ডন্ডার পদ্ধতির নাম।
সিঙ্গেলেশনএলিমিনেশন

2
  • গণনার সময়।
  • নাম ছাড়া ফাংশন।
  • একটি ফাংশন এবং অনেকগুলি ব্যবহারের কার্যকারিতা অর্জন করতে।

একটি সাধারণ উদাহরণ বিবেচনা করে,

# CREATE ONE FUNCTION AND USE IT TO PERFORM MANY OPERATIONS ON SAME TYPE OF DATA STRUCTURE.
def variousUse(a,b=lambda x:x[0]):
    return [b(i) for i in a]

dummyList = [(0,1,2,3),(4,5,6,7),(78,45,23,43)]
variousUse(dummyList)                           # extract first element
variousUse(dummyList,lambda x:[x[0],x[2],x[3]]) # extract specific indexed element
variousUse(dummyList,lambda x:x[0]+x[2])        # add specific elements
variousUse(dummyList,lambda x:x[0]*x[2])        # multiply specific elements

1

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

fun = lambda a, b: a ** b # a pointless use of lambda
map(fun, someList)

বা

def fun(a, b): return a ** b # more readable
map(fun, someList)

উভয় from operator import pow;map(pow, someList)এবং (a**b for a,b in someList)আরও পাঠযোগ্য।
ইনকিউ

1

ল্যাম্বডাসের জন্য একটি ব্যবহার আমি পেয়েছি ... এটি ডিবাগ বার্তায় রয়েছে।

যেহেতু ল্যাম্বডাসকে অলসভাবে মূল্যায়ন করা যায় আপনার এই কোড থাকতে পারে:

log.debug(lambda: "this is my message: %r" % (some_data,))

সম্ভবত ব্যয়বহুল পরিবর্তে:

log.debug("this is my message: %r" % (some_data,))

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

অবশ্যই এটির জন্য কাজ করার জন্য ব্যবহারের লগিং মডিউলটিকে "অলস প্যারামিটার" হিসাবে (যেমন আমার লগিং মডিউলটি করে) হিসাবে ল্যাম্বডাসকে সমর্থন করতে হবে।

চাহিদা সামগ্রী তৈরির জন্য অলস মূল্যায়নের অন্য কোনও ক্ষেত্রে একই ধারণা প্রয়োগ করা যেতে পারে।

উদাহরণস্বরূপ এই কাস্টম টার্নারি অপারেটর:

def mif(condition, when_true, when_false):
    if condition:
         return when_true()
    else:
         return when_false()

mif(a < b, lambda: a + a, lambda: b + b)

পরিবর্তে:

def mif(condition, when_true, when_false):
    if condition:
         return when_true
    else:
         return when_false

mif(a < b, a + a, b + b)

ল্যাম্বডাসের সাথে শুধুমাত্র শর্ত দ্বারা নির্বাচিত অভিব্যক্তি মূল্যায়ন করা হবে, ল্যাম্বডাস ছাড়াই উভয়কেই মূল্যায়ন করা হবে।

অবশ্যই আপনি ল্যাম্বডাসের পরিবর্তে ফাংশনগুলি ব্যবহার করতে পারেন তবে সংক্ষিপ্ত প্রকাশের জন্য ল্যাম্বডাস (গ) ঝুঁকিতে রয়েছে।


4
এনবি এর মধ্যে loggingইতিমধ্যে অলস ফর্ম্যাটিং রয়েছে: log.debug("this is my message: %r", some_data)কেবলমাত্র / যদি বার্তার অনুরোধ করা হয় তখন বিন্যাস হবে।
j08lue

@ j08lue ল্যাম্বদা পদ্ধতিটি ডিবাগ আউটপুট উত্পাদিত না হওয়ার ক্ষেত্রে সমস্ত কিছুর মূল্যায়ন এড়িয়ে যায়, আপনি যে ক্ষেত্রে দেখান some_dataএকটি ব্যয়বহুল এক্সপ্রেশন বা ফাংশন / পদ্ধতি কল হতে পারে।
গ্লুসিএটার

0

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

ইজি:

এই স্বাক্ষর সহ আপনার একটি ফাংশন রয়েছে: মাই ফাংশন (ডেটা, কলব্যাক ফাংশন)।

আপনি এমন একটি ফাংশন পাস করতে চান যাতে 2 টি উপাদান যুক্ত হয়।

ল্যাম্বদা ব্যবহার:

myFunction(data, (lambda x, y : x + y))

পাইথোনিক উপায়:

import operator
myFunction(data, operator.add)

অথবা অবশ্যই এটি একটি সহজ উদাহরণ, তবে অপারেটর মডিউল সরবরাহ করে এমন অনেকগুলি স্টাফ রয়েছে, যাতে তালিকা এবং ডিকের জন্য আইটেম সেটার / গেটারগুলি অন্তর্ভুক্ত থাকে। সত্যিই ঠাণ্ডা.


-1

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

my_list.sort(key=lambda o: o.x)

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


-2

ল্যাম্বদা নতুন ফাংশন তৈরির জন্য দরকারী:

>>> def somefunc(x): return lambda y: x+y
>>> f = somefunc(10)
>>> f(2)
12
>>> f(4)
14
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.