পাইথনে কি বিল্টিন আইডেন্টিটি ফাংশন রয়েছে?


145

আমি এমন একটি ফাংশনটির দিকে ইঙ্গিত করতে চাই যা কিছুই করে না:

def identity(*args)
    return args

আমার ব্যবহারের কেসটি এরকম কিছু

try:
    gettext.find(...)
    ...
    _ = gettext.gettext
else:
    _ = identity

অবশ্যই, আমি identityউপরের সংজ্ঞায়িতটি ব্যবহার করতে পারি , তবে একটি বিল্ট-ইন অবশ্যই দ্রুত চলবে (এবং আমার নিজের দ্বারা প্রবর্তিত বাগগুলি এড়ানো হবে)।

স্পষ্টতই, mapএবং পরিচয়ের জন্য filterব্যবহার Noneকরুন, তবে এটি তাদের বাস্তবায়নের জন্য নির্দিষ্ট।

>>> _=None
>>> _("hello")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable

6
আপনি কি বলতে চাইছেন map and filter use None for the identity?
ম্যাট ফেনউইক

15
@ ম্যাটফেনউইক:map(None, [1, 2, 3])
গ্রেগ হিউগিল

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

11
@ গ্রেগ হিউগিল: দুঃখের বিষয়, পাইথন ৩.x এ কাজ করে না।
ইথান ফুরম্যান

6
@ গ্রেগ হিউগিল আমার খারাপ। গুগল করার পরে আমি ডক থেকে তা নিয়েছিলাম। তবে পাইথন 2.x ডকটি সর্বদা প্রথম আসে ...
রডস

উত্তর:


99

আরও কিছু গবেষণা করার পরেও তা নেই, 1673203 ইস্যুতে একটি বৈশিষ্ট্য জিজ্ঞাসা করা হয়েছিল এবং রেমন্ড হেট্টিংগার থেকে বলেছিলেন যে সেখানে হবে না :

লোকেরা তাদের নিজস্ব তুচ্ছ পাস-থ্রো লিখতে দেয় এবং স্বাক্ষর এবং সময় ব্যয় সম্পর্কে চিন্তা করে।

সুতরাং এটির আরও ভাল উপায় আসলে (একটি ল্যাম্বডা ফাংশনটির নামকরণ এড়ানো হয়):

_ = lambda *args: args
  • সুবিধা: পরামিতিগুলির যে কোনও সংখ্যা লাগে takes
  • অসুবিধা: ফলাফলটি পরামিতিগুলির একটি বক্সযুক্ত সংস্করণ

অথবা

_ = lambda x: x
  • সুবিধা: প্যারামিটারের ধরন পরিবর্তন করে না
  • অসুবিধা: ঠিক 1 অবস্থানগত প্যারামিটার লাগে

13
মনে রাখবেন এটি কোনও পরিচয় ফাংশন নয়।
মার্সিন

1
@ মার্সিন মন্তব্য করার জন্য ধন্যবাদ। কাউকে বিভ্রান্ত না করার জন্য আমি দুজনের সুবিধাগুলি / ত্রুটিগুলি যুক্ত করেছি। এবং এখন, আমি সত্যিই বিশ্বাস করি যে কোনও বিল্টিন ফাংশন হওয়া উচিত ছিল যা কোনও সংখ্যক পরামিতি গ্রহণ করে এবং একটি সত্য পরিচয় :)
আরডিএস

7
চমৎকার উত্তর. তবে, একাধিক পরামিতি গ্রহণের সময় সত্যিকারের পরিচয় ফাংশনটি কী ফিরে আসবে?
মার্সিন

5
@ মার্সিন: না, কেবল তিনি তাঁর প্রশ্নে যা চেয়েছিলেন ঠিক সেভাবেই চলছে।
ইথান ফুরম্যান

4
হ্যাঁ ধন্যবাদ, আমার একটি তুচ্ছ lambda x: xপরিচয় ফাংশন রয়েছে যা একটি স্ট্রিং প্যারামিটারের জন্য কাজ করে। @ মার্সিন আমি আশা করি আমি করতে পারি lambda *args: *args:-)
আরডিএস

28

Https://en.wikedia.org/wiki/Identity_function এ সংজ্ঞায়িত হিসাবে একটি পরিচয় ফাংশন, একটি একক যুক্তি নেয় এবং এটিকে অপরিবর্তিত রাখে:

def identity(x):
    return x

আপনি কি যখন আপনি বলে জন্য জিজ্ঞাসা করা হয় আপনি স্বাক্ষর চান def identity(*args)হয় না কঠোরভাবে একটি পরিচয় ফাংশন, আপনি এটা একাধিক আর্গুমেন্ট নিতে চান। এটি ঠিক আছে, তবে পাইথন ফাংশনগুলি একাধিক ফলাফল না ফেরায় আপনি কোনও সমস্যার মুখোমুখি হচ্ছেন, সুতরাং আপনাকে সেই সমস্ত আর্গুমেন্টগুলিকে এক রিটার্ন ভ্যালুতে ক্র্যাম করার উপায় খুঁজে বের করতে হবে।

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

>>> def mv_identity(*args):
...     return args
...
>>> mv_identity(1,2,3)
(1, 2, 3)
>>> # So far, so good. But what happens now with single arguments?
>>> mv_identity(1)
(1,)

এবং এই সমস্যাটি দ্রুত সমাধান করা অন্যান্য সমস্যাগুলি দেয়, যেমন এখানে বিভিন্ন উত্তর দেখিয়েছে।

সুতরাং, সংক্ষেপে, পাইথনে কোনও পরিচয় ফাংশন সংজ্ঞায়িত করা হয়নি কারণ:

  1. আনুষ্ঠানিক সংজ্ঞা (একক যুক্তি ফাংশন) যে দরকারী নয়, এবং লিখতে তুচ্ছ।
  2. একাধিক যুক্তিতে সংজ্ঞাটি প্রসারিত করা সাধারণভাবে সংজ্ঞায়িত নয় এবং আপনি আপনার নিজের সংস্করণটিকে নির্দিষ্ট করে তুলতে আরও ভাল যা আপনার নির্দিষ্ট পরিস্থিতির জন্য আপনার প্রয়োজন মতো কাজ করে।

আপনার সুনির্দিষ্ট ক্ষেত্রে জন্য,

def dummy_gettext(message):
    return message

প্রায় অবশ্যই আপনি যা চান - এটি একটি ফাংশন যার একই কলিং কনভেনশন রয়েছে এবং ফিরে gettext.gettextআসে, যা তার যুক্তিটি অপরিবর্তিত রেখে দেয় এবং এটি কী করে এবং এটি ব্যবহার করার উদ্দেশ্যে কী তা বর্ণনা করার জন্য পরিষ্কারভাবে নামকরণ করা হয়েছে। পারফরম্যান্স যদি এখানে বিবেচনা করা হত তবে আমি চমকে উঠব।


"সমস্যার সমাধান করা অন্যান্য সমস্যাগুলি যেমন উত্তরগুলি দেখিয়েছে" এর সাথে আপনি কী উত্তরগুলি উল্লেখ করেছেন তা আমি দেখতে পাচ্ছি না। বিশেষত, এটি ব্যবহারের জন্য যথেষ্ট id= lambda *args: args if len(args)>1 else args[0]
সর্বাধিক

21

আপনার ভাল কাজ করবে। প্যারামিটারের সংখ্যা ঠিক হয়ে গেলে আপনি এইরকম একটি বেনামি ফাংশন ব্যবহার করতে পারেন:

lambda x: x

8
আপনিও ভারার্গস সঙ্গে এই কাজ করতে পারেন: lambda *args: args। এটি সত্যিই একটি শৈলীগত পছন্দ।

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

4
@ ডেলান @ আরডিএস - *argsসংস্করণটির ভিন্ন ভিন্ন রিটার্ন রয়েছে, তাই তারা একক যুক্তির ক্ষেত্রেও সমতুল্য নয়।
মার্সিন

8
@ ডেলানন: আপনি বলেছিলেন যে এটি একটি স্টাইলিস্টিক পছন্দ, যা ভুলভাবে বোঝায় যে দুটি রূপের শব্দার্থবিজ্ঞানের মধ্যে কোনও পার্থক্য নেই।
মার্সিন

1
@ মার্সিন: আমি দুর্ভাগ্যজনক যে যদি আমি তা বোঝায়। আমি এর মধ্যে defএবং এই lambdaজাতীয় সাধারণ ফাংশনগুলির জন্য পছন্দ বোঝাই।

7

পাইথনে কোনও অন্তর্নির্মিত পরিচয় ফাংশন নেই। একটি অনুকরণ Haskell, এর idফাংশন হবে:

identity = lambda x, *args: (x,) + args if args else x

ব্যবহারের উদাহরণ:

identity(1)
1
identity(1,2)
(1, 2)

যেহেতু identityপ্রদত্ত যুক্তিগুলি ফিরিয়ে দেওয়া ব্যতীত অন্য কিছুই করে না, তাই আমি মনে করি না যে এটি একটি দেশীয় বাস্তবায়নের চেয়ে ধীর হয়।


সেটআপটি সম্পূর্ণ হওয়ার পরে আপনি যা করেন তা নির্বিশেষে এটি কলটি নিজেই তৈরি হয় time
চিপনার

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

1
একটি ব্যবহারকারী-সংজ্ঞায়িত ফাংশন একটি কল ব্যয়বহুল হিসাবে কমপক্ষে একটি কল হিসাবে একটি বিল্ট-ইন ফাংশন, এবং সম্ভবত আরো যাতে কারণ একবার আপনি ব্যবহারকারী-সংজ্ঞায়িত ফাংশন বলা হয়েছে, অন্য কিছু এটা ডাকা হতে পারে হয় আরো ব্যবহারকারী-সংজ্ঞায়িত বা বিল্ট কর্মে।
চিপনার

6

না, নেই।

মনে রাখবেন যে আপনার identity:

  1. ল্যাম্বদা * আরগস: আরগ্সের সমতুল্য
  2. এর আর্গ বাক্স করবে - যেমন

    In [6]: id = lambda *args: args
    
    In [7]: id(3)
    Out[7]: (3,)

সুতরাং, আপনি lambda arg: argযদি সত্যিকারের পরিচয় ফাংশন চান তবে আপনি ব্যবহার করতে পারেন।

এনবি: এই উদাহরণটি বিল্ট-ইন idফাংশনটির ছায়া দেবে (যা আপনি সম্ভবত কখনও ব্যবহার করতে পারবেন না)।


1
নোট করুন যে আইডি একটি অন্তর্নির্মিত ফাংশন, এবং এই স্নিপেট এটি ওভাররাইট করবে।
Arnie97

@ আরনি97 মেলা! আমি ভুলে গিয়েছিলামid
মার্সিন

4

গতিটি যদি গুরুত্বপূর্ণ না হয় তবে এটি সমস্ত ক্ষেত্রে পরিচালনা করবে:

def identity(*args, **kwargs):
    if not args:
        if not kwargs:
            return None
        elif len(kwargs) == 1:
            return  next(iter(kwargs.values()))
        else:
            return (*kwargs.values(),)
    elif not kwargs:
        if len(args) == 1:
            return args[0]
        else:
            return args
    else:
        return (*args, *kwargs.values())

ব্যবহারের উদাহরণ:

print(identity())
None
$identity(1)
1
$ identity(1, 2)
(1, 2)
$ identity(1, b=2)
(1, 2)
$ identity(a=1, b=2)
(1, 2)
$ identity(1, 2, c=3)
(1, 2, 3)

1

একক যুক্তি ফাংশনের স্টাব

gettext.gettext(ওপির উদাহরণ ব্যবহারের ক্ষেত্রে) একটি একক যুক্তি গ্রহণ করে message,। যদি এর জন্য কোনও স্টাবের প্রয়োজন [message]হয় তবে message( def identity(*args): return args) এর পরিবর্তে ফিরে আসার কোনও কারণ নেই । এইভাবে উভয়

_ = lambda message: message

def _(message):
    return message

পুরোপুরি ফিট।

... তবে একটি অন্তর্নিহিত অবশ্যই দ্রুত চলবে (এবং আমার নিজের দ্বারা প্রবর্তিত বাগগুলি এড়ানো হবে)।

এই ধরনের তুচ্ছ মামলায় বাগগুলি সবে প্রাসঙ্গিক। পূর্বনির্ধারিত ধরণের আর্গুমেন্টের জন্য, বলুন str, আমরা str()নিজেকে একটি পরিচয় ফাংশন হিসাবে ব্যবহার করতে পারি ( স্ট্রিংয়ের কারণে এটি বস্তুর পরিচয়ও ধরে রাখে, নীচের idনোটটি দেখুন) এবং ল্যাম্বডা সমাধানের সাথে এর কার্যকারিতা তুলনা করুন:

$ python3 -m timeit -s "f = lambda m: m" "f('foo')"
10000000 loops, best of 3: 0.0852 usec per loop
$ python3 -m timeit "str('foo')"
10000000 loops, best of 3: 0.107 usec per loop

একটি মাইক্রো অপ্টিমাইজেশন সম্ভব। উদাহরণস্বরূপ, নিম্নলিখিত সিথন কোড:

test.pyx

cpdef str f(str message):
    return message

তারপর:

$ pip install runcython3
$ makecython3 test.pyx
$ python3 -m timeit -s "from test import f" "f('foo')"
10000000 loops, best of 3: 0.0317 usec per loop

বিল্ড-ইন অবজেক্ট আইডেন্টিটি ফাংশন

সিপিথনে তার স্মৃতি ঠিকানা, কোনও বস্তুর 'পরিচয়'id দেয় এমন কোনও অন্তর্নিহিত ফাংশন (কোনও নির্দিষ্ট সামগ্রীর জন্য একটি অনন্য শনাক্তকারীর অর্থ অপারেটরের সাথে তুলনা করে ) অর্থ কোনও অন্তর্নিহিত ফাংশনটিকে বিভ্রান্ত করবেন না ।==


একটি 40% স্পিডআপ "এটি খুব উপযুক্ত বলে মনে হচ্ছে না"? যেসব ক্ষেত্রে চলমান কোনও ক্রিয়াকলাপের জন্য পরিচয়টি "ডিফল্ট ফিল্টার" হিসাবে পরিচালিত হয়, সেখানে একবার 10,000x10,000 পিক্সেলের চিত্রের প্রতি চ্যানেল (সম্ভবত প্রতিদিন নয় তবে অবশ্যই অস্বাভাবিক নয়) বলুন, এটি 25 এবং 9 এর মধ্যে পার্থক্য difference সেকেন্ডের ফাঁসির সময়! নির্বিশেষে, সাইথন উদাহরণের জন্য আপনাকে ধন্যবাদ।
9999 ইয়ার্স

@ 9999 বছর আমি সম্মত আমি যোগ্যতা মন্তব্য মুছে ফেলেছি। উত্তর উন্নতির জন্য ধন্যবাদ। আমি আপনার শীর্ষে কিছু ছোটখাটো পরিবর্তন করেছি।
সাজন

আপনার যদি 10,000x10,000 পিক্সেল চিত্র থাকে তবে আমি দৃ strongly়রূপে নমপির মতো কিছু ব্যবহার করে ভেক্টরাইজড ক্রিয়াকলাপগুলি ব্যবহার করার পরামর্শ দিচ্ছি। এটি দ্রুততর হবে, উপায় কম মেমরি ব্যবহার করবে এবং সিথন কোড লেখার প্রয়োজন হবে না।
এন্থনিবেল

-2

সুতোটি বেশ পুরানো। তবে এখনও এই পোস্ট করতে চেয়েছিলেন।

উভয় যুক্তি এবং অবজেক্টের জন্য একটি পরিচয় পদ্ধতি তৈরি করা সম্ভব। নীচের উদাহরণে, ObjOut ObjIn এর জন্য একটি পরিচয়। উপরের অন্যান্য সমস্ত উদাহরণ ডিক ** কোয়ার্গের সাথে কাজ করে নি।

class test(object):
    def __init__(self,*args,**kwargs):
        self.args = args
        self.kwargs = kwargs
    def identity (self):
        return self

objIn=test('arg-1','arg-2','arg-3','arg-n',key1=1,key2=2,key3=3,keyn='n')
objOut=objIn.identity()
print('args=',objOut.args,'kwargs=',objOut.kwargs)

#If you want just the arguments to be printed...
print(test('arg-1','arg-2','arg-3','arg-n',key1=1,key2=2,key3=3,keyn='n').identity().args)
print(test('arg-1','arg-2','arg-3','arg-n',key1=1,key2=2,key3=3,keyn='n').identity().kwargs)

$ py test.py
args= ('arg-1', 'arg-2', 'arg-3', 'arg-n') kwargs= {'key1': 1, 'keyn': 'n', 'key2': 2, 'key3': 3}
('arg-1', 'arg-2', 'arg-3', 'arg-n')
{'key1': 1, 'keyn': 'n', 'key2': 2, 'key3': 3}

এটি একটি রেফারেন্সের মতো দেখায়, যদি তাই হয় তবে কোথা থেকে এসেছে?
জেফ পেকেট

@ জেফপুকেটআইআই আমি আপনার প্রশ্নটি অনুসরণ করি না। আপনি কি জিজ্ঞাসা করছেন যে নতুন অবজেক্টটি একটি রেফারেন্স কিনা?
সুদ

আপনি "একটি পরিচয় তৈরি করা সম্ভব ..." এর জন্য একটি ব্লককোট হাইলাইট ব্যবহার করেছেন যা অন্য উত্সের একটি রেফারেন্স বোঝায়। এগুলি যদি আপনার নিজস্ব শব্দ হয় তবে আমি এটিকে উদ্ধৃতি হিসাবে হাইলাইট না করার পরামর্শ দেব। সত্যিই বড় ব্যাপার নয়। তবে এটি যদি অন্য উত্স থেকে উদ্ধৃতি হয়, তবে আপনার এটির একটি উল্লেখ অন্তর্ভুক্ত করা উচিত।
জেফ পেকেট

আসল প্রশ্নের map(identity, [1, 2, 3])রিটার্নের উত্তর কীভাবে দেবেন [1, 2, 3]?
rd

class test1(object): def __init__(self,*args,**kwargs): self.args = args self.kwargs = kwargs def identity (self): return self.args print(test1([1,2,3]).identity())-> ফলাফল: ([1, 2, 3],)
সুড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.