ল্যাম্বডায় অটো টুপল আনপ্যাকিংয়ের জন্য পাইথন 3 এর সমতুল্য কী?


97

নিম্নলিখিত পাইথন 2 কোডটি বিবেচনা করুন

In [5]: points = [ (1,2), (2,3)]

In [6]: min(points, key=lambda (x, y): (x*x + y*y))
Out[6]: (1, 2)

এটি পাইথন 3 এ সমর্থিত নয় এবং আমাকে নিম্নলিখিতগুলি করতে হবে:

>>> min(points, key=lambda p: p[0]*p[0] + p[1]*p[1])
(1, 2)

এটা খুব কুৎসিত। ল্যাম্বদা যদি কোনও ফাংশন হত তবে আমি করতে পারতাম

def some_name_to_think_of(p):
  x, y = p
  return x*x + y*y

পাইথন 3-এ এই বৈশিষ্ট্যটি সরিয়ে ফেলা কোডটিকে কুৎসিত পদ্ধতিতে কাজ করতে বাধ্য করে (যাদু সূচকগুলি দিয়ে) বা অপ্রয়োজনীয় ফাংশন তৈরি করে (সবচেয়ে উদ্বেগজনক অংশটি এই অপ্রয়োজনীয় ফাংশনগুলির জন্য ভাল নাম চিন্তা করা)

আমি মনে করি ফিচারটি কমপক্ষে একা ল্যাম্বডাসে যোগ করা উচিত। একটি ভাল বিকল্প আছে?


আপডেট: আমি উত্তরটিতে ধারণাটি প্রসারিত করতে নিম্নলিখিত সাহায্যকারী ব্যবহার করছি

def star(f):
  return lambda args: f(*args)

min(points, key=star(lambda x,y: (x*x + y*y))

আপডেট 2: এর জন্য একটি ক্লিনার সংস্করণstar

import functools

def star(f):
    @functools.wraps(f):
    def f_inner(args):
        return f(*args)
    return f_inner

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

4
আমি তাও পাই না, তবে মনে হচ্ছে বিডিএফএল lambdaএকই মনোভাবের সাথে যেমন বিরোধিতা করেছে map, reduceএবং filter
কুয়াদিউ

4
lambdaএটি মূলত ভাষার উপর এক ঝাঁকুনি হিসাবে পাই 3 কে অপসারণের জন্য প্রস্তুত ছিল। তবে বেনামে কার্যকারিতা সংজ্ঞায়নের জন্য সঠিক বিকল্পের বিষয়ে কেউ একমত হতে পারেনি, তাই শেষ পর্যন্ত গাইদো পরাজয়ে নিজের হাত ছুঁড়ে মারলেন এবং সেটিই ছিল।
রুইপি

4
বেনাম ফাংশনগুলির যে কোনও উপযুক্ত ভাষায় অবশ্যই আবশ্যক এবং আমি ল্যাম্বডাসকে বেশ পছন্দ করি। আমাকে এমন বিতর্কের ছটফটানি পড়তে হবে। (এছাড়াও, যদিও mapএবং filterবোধগম্যতার দ্বারা সেরা প্রতিস্থাপন করা হয়েছে, আমি পছন্দ করি reduce)
njzk2

13
পাইথন 3 সম্পর্কে একটি জিনিস আমি অপছন্দ করি ...

উত্তর:


34

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

আসলে, "কোনও উপায় নেই" বলার অপেক্ষা রাখে না, তৃতীয় উপায়টি কেবলমাত্র পরামিতিগুলি প্রকাশ করার জন্য আরও একটি স্তরের ল্যাম্বডা কলিং বাস্তবায়ন করা যেতে পারে - তবে এটি আপনার দুটি পরামর্শের চেয়ে একবারে আরও অদক্ষ এবং পড়ার পক্ষে কঠিন হবে:

min(points, key=lambda p: (lambda x,y: (x*x + y*y))(*p))

পাইথন ৩.৮ আপডেট করুন

এখন পর্যন্ত পাইথন ৩.৮ আলফা ১ পাওয়া যায় এবং পিইপি 572- অ্যাসাইনমেন্ট এক্সপ্রেশনগুলি কার্যকর করা হয়।

সুতরাং, যদি কোনও ল্যাম্বদার অভ্যন্তরে একাধিক এক্সপ্রেশন সম্পাদন করতে কোনও কৌশল ব্যবহার করে - আমি সাধারণত একটি টিপল তৈরি করে এবং এর শেষ উপাদানটি ফিরিয়ে দিলে এটি করা সম্ভব:

>>> a = lambda p:(x:=p[0], y:=p[1], x ** 2 + y ** 2)[-1]
>>> a((3,4))
25

একটি মনে রাখা উচিত যে এই ধরণের কোড একটি পূর্ণ ফাংশন থাকার চেয়ে খুব কমই পাঠযোগ্য বা ব্যবহারিক হবে be তবুও, সম্ভাব্য ব্যবহার রয়েছে - যদি এই pointওপেন করে এমন বিভিন্ন ওয়ান-লাইনার থাকে তবে এটি একটি নেমটুপল রাখার জন্য মূল্যবান হতে পারে, এবং কার্যনির্বাহী অভিব্যক্তিটি নামডটপলে ইনকামিং ক্রমটি "কাস্ট" করতে কার্যকরভাবে ব্যবহার করতে পারে:

>>> from collections import namedtuple
>>> point = namedtuple("point", "x y")
>>> b = lambda s: (p:=point(*s), p.x ** 2 + p.y ** 2)[-1]

4
এবং অবশ্যই, আমি উল্লেখ করতে ভুলে গেছি যে এটি করার "এক এবং সুস্পষ্ট" defউপায়টি আসলে তিনটি লাইন ফাংশনটি ব্যয় করে এনএমএমের নীচে প্রশ্নে উল্লেখ করা হয়েছে some_name_to_think-of
jsbueno

4
এই উত্তরটি এখনও কিছু দর্শক দেখতে পায় - পিইপি 572 বাস্তবায়নের সাথে ল্যাম্বডা এক্সপ্রেশনটির ভিতরে ভেরিয়েবলগুলি তৈরি করার উপায় থাকতে হবে, যেমন:key = lambda p: (x:=p[0], y:=p[1], x ** 2 + y ** 2)[-1]
জসবুওনো

4
অ্যাসাইনমেন্ট এক্সপ্রেশন !! আমি (আনন্দদায়ক) অবাক হয়েছি তারা এটিকে তৈরি করেছে
স্টিফেনবোশ

24

Http://www.python.org/dev/peps/pep-3113/ এর মতে টুপল আনপ্যাকিং শেষ হয়ে গেছে, এবং 2to3সেগুলি এভাবে অনুবাদ করবে:

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

lambda (x, y): x + y

অনুবাদ করা হবে:

lambda x_y: x_y[0] + x_y[1]

যা আপনার বাস্তবায়নের সাথে বেশ মিল।


4
ভাল যে এটি লুপ বা বোধগম্যতার জন্য সরানো হয়নি
বালকি

12

পাইথন 2 টি আর্গুমেন্টের আনপ্যাকিংয়ের কোনও ভাল সাধারণ বিকল্প আমি জানি না। এখানে বেশ কয়েকটি পরামর্শ যা কিছু ক্ষেত্রে কার্যকর হতে পারে:

  • আপনি যদি একটি নাম চিন্তা করতে না পারেন; কীওয়ার্ড প্যারামিটারের নামটি ব্যবহার করুন:

    def key(p): # more specific name would be better
        x, y = p
        return x**2 + y**3
    
    result = min(points, key=key)
    
  • আপনি যদি দেখতে পারেন যে namedtupleকোনওটি আপনার কোডটিকে আরও পাঠযোগ্য করে তোলে যদি তালিকাটি একাধিক জায়গায় ব্যবহার করা হয়:

    from collections import namedtuple
    from itertools import starmap
    
    points = [ (1,2), (2,3)]
    Point = namedtuple('Point', 'x y')
    points = list(starmap(Point, points))
    
    result = min(points, key=lambda p: p.x**2 + p.y**3)
    

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

5

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

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

points = [(1,2), (2,3)]
print(min(points, key=lambda y: next(x*x + y*y for x,y in (lambda a: (yield a))(y))))

একটি মোড়ক ব্যবহারের স্বীকৃত উত্তরের সাথে তুলনা করে, এই সমাধানটি আর্গুমেন্টগুলিকে সম্পূর্ণরূপে গঠন করতে সক্ষম হয়, তবে মোড়ক কেবল প্রথম স্তরটিকেই তৈরি করে। এটাই,

values = [(('A',1),'a'), (('B',0),'b')]
print(min(values, key=lambda y: next(b for (a,b),c in (lambda x: (yield x))(y))))

তুলনায়

values = [(('A',1),'a'), (('B',0),'b')]
print(min(points, key=lambda p: (lambda a,b: (lambda x,y: (y))(*a))(*p)))

বিকল্পভাবে একটি করতে পারেন

values = [(('A',1),'a'), (('B',0),'b')]
print(min(points, key=lambda y: next(b for (a,b),c in [y])))

বা কিছুটা ভাল

print(min(values, key=lambda y: next(b for ((a,b),c) in (y,))))

এটি কেবল এটি করা যেতে পারে এমন পরামর্শ দেওয়ার জন্য, এবং এটি একটি সুপারিশ হিসাবে নেওয়া উচিত নয়।


1

আমার মনে হয় আরও ভাল সিনট্যাক্স হ'ল x * x + y * y let x, y = point, letকীওয়ার্ডটি আরও যত্ন সহকারে বেছে নেওয়া উচিত।

ডাবল ল্যাম্বদা হল নিকটতম সংস্করণ। lambda point: (lambda x, y: x * x + y * y)(*point)

আমরা এটির যথাযথ নাম দিলে হাই-অর্ডার ফাংশন সহায়ক সহায়ক হবে।

def destruct_tuple(f):
  return lambda args: f(*args)

destruct_tuple(lambda x, y: x * x + y * y)

0

চুয়াডু পরামর্শ এবং আনপ্যাকিংয়ের বিষয়ে আপনার মন্তব্যের ভিত্তিতে এখনও উপলব্ধি উপস্থিত রয়েছে, আপনি ব্যবহার করে এটি ব্যবহার করতে পারেন numpy.argmin:

result = points[numpy.argmin(x*x + y*y for x, y in points)]

0

আরেকটি বিকল্প হ'ল এটি এমন একটি জেনারেটরে লিখুন যেখানে একটি টিউপল তৈরি হয় যেখানে কীটি প্রথম উপাদান। টিপলসকে শুরু থেকে শেষের সাথে তুলনা করা হয় যাতে ক্ষুদ্রতম প্রথম উপাদানটির সাথে টিপলটি ফিরে আসে। তারপরে আপনি মানটি পেতে ফলাফলটিতে সূচক করতে পারেন।

min((x * x + y * y, (x, y)) for x, y in points)[1]

0

আপনাকে প্রথমে টিপলটি আনপ্যাক করতে হবে কিনা তা বিবেচনা করুন:

min(points, key=lambda p: sum(x**2 for x in p))

অথবা আনপ্যাক করার সময় আপনাকে সুস্পষ্ট নাম সরবরাহ করতে হবে কিনা:

min(points, key=lambda p: abs(complex(*p))
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.