यह कई मूल्यों को वापस करने के लिए एक समारोह के लिए pythonic है?


81

अजगर में, आप एक फ़ंक्शन कई मान वापस कर सकते हैं। यहाँ एक उदाहरण दिया गया है:

def divide(x, y):
    quotient = x/y
    remainder = x % y
    return quotient, remainder  

(q, r) = divide(22, 7)

यह बहुत उपयोगी लगता है, लेकिन ऐसा लगता है कि इसका दुरुपयोग भी किया जा सकता है ("वेल..फंक्शन एक्स पहले से ही गणना करता है कि हमें एक मध्यवर्ती मूल्य के रूप में क्या चाहिए। आइए एक्स एक्स वापसी करें कि मूल्य भी")।

आपको लाइन कब खींचनी चाहिए और एक अलग विधि निर्धारित करनी चाहिए?

जवाबों:


107

बिल्कुल (आपके द्वारा दिए गए उदाहरण के लिए)।

ट्यूलिप पायथन में प्रथम श्रेणी के नागरिक हैं

एक बिल्टिन फ़ंक्शन है divmod()जो वास्तव में ऐसा करता है।

q, r = divmod(x, y) # ((x - x%y)/y, x%y) Invariant: div*y + mod == x

वहाँ अन्य उदाहरण हैं: zip, enumerate, dict.items

for i, e in enumerate([1, 3, 3]):
    print "index=%d, element=%s" % (i, e)

# reverse keys and values in a dictionary
d = dict((v, k) for k, v in adict.items()) # or 
d = dict(zip(adict.values(), adict.keys()))

बीटीडब्ल्यू, कोष्ठक ज्यादातर समय आवश्यक नहीं हैं। पायथन लाइब्रेरी से उद्धरण संदर्भ :

ट्यूपल्स का निर्माण कई तरीकों से किया जा सकता है:

  • खाली टपल को दर्शाने के लिए कोष्ठक की एक जोड़ी का उपयोग करना: ()
  • सिंगलटन टपल के लिए अनुगामी अल्पविराम का उपयोग करना: a, या (a)
  • अल्पविराम से अलग आइटम: ए, बी, सी या (ए, बी, सी)
  • Tuple () बिल्ट-इन: tuple () या tuple (iterable) का उपयोग करना

कार्यों को एकल उद्देश्य की सेवा करनी चाहिए

इसलिए उन्हें एक ही वस्तु वापस करनी चाहिए। आपके मामले में यह ऑब्जेक्ट टपल है। एक तदर्थ यौगिक डेटा संरचना के रूप में टपल पर विचार करें। ऐसी भाषाएं हैं जहां लगभग हर एक फ़ंक्शन कई मान देता है (लिस्प में सूची)।

कभी-कभी इसके (x, y)बजाय वापस जाने के लिए पर्याप्त है Point(x, y)

नाम दिया टुपल्स

पायथन 2.6 में नामित टुपल्स की शुरुआत के साथ, सादे ट्यूपल्स के बजाय ट्यूपल्स नाम की वापसी के लिए कई मामलों में यह बेहतर है।

>>> import collections
>>> Point = collections.namedtuple('Point', 'x y')
>>> x, y = Point(0, 1)
>>> p = Point(x, y)
>>> x, y, p
(0, 1, Point(x=0, y=1))
>>> p.x, p.y, p[0], p[1]
(0, 1, 0, 1)
>>> for i in p:
...   print(i)
...
0
1

1
ट्यूपल्स का उपयोग करने की क्षमता इतनी आसान है। मैं वास्तव में कुछ समय जावा में उस क्षमता को याद करता हूं।
MBCook

3
नामांकित tuples का उल्लेख करने के लिए बहुत बहुत धन्यवाद। मैं कुछ इस तरह की तलाश में था।
8:10 बजे

सीमित रिटर्न मानों के लिए, तानाशाह () सरल / तेज हो सकता है (विशेषकर यदि फ़ंक्शन तब REST API और JSON के लिए उपयोग किया जाता है)। मेरे सिस्टम पर, def test_nt (): Point = nametuple ('Point', ['x', 'y']) p = Point (10.5, 11.5) json.dumps (p._asdict ()) 619 μs / पाश , def test_dict (): d = {'x': 10.5, 'y': 11.5} json.dumps (d) 15.9μs / पाश लेता है .... तो> 50x तेज
comte

@ कॉम: हाँ, Point(10.5, 11.5)की तुलना में 6 गुना धीमा है {'x': 10.5, 'y':11.5}। पूर्ण समय 635 ns +- 26 nsबनाम हैं105 ns +- 4 ns । यह संभावना नहीं है कि या तो आवेदन में एक अड़चन होगी - तब तक अनुकूलन न करें जब तक कि आपका प्रोफाइलर अन्यथा नहीं कहता। फ़ंक्शन स्तर पर तब तक कक्षाएं न बनाएं जब तक आपको पता न हो कि आपको इसकी आवश्यकता क्यों है। यदि आपके API को dictउपयोग की आवश्यकता है dict- इसका प्रदर्शन से कोई लेना-देना नहीं है।
JFS

27

सबसे पहले, ध्यान दें कि पायथन निम्नलिखित के लिए अनुमति देता है (कोष्ठक की कोई आवश्यकता नहीं):

q, r = divide(22, 7)

आपके प्रश्न के संबंध में, कोई कठिन और तेज़ नियम नहीं है। सरल (और आमतौर पर वंचित) उदाहरणों के लिए, ऐसा लग सकता है कि किसी दिए गए फ़ंक्शन के लिए एक ही उद्देश्य के लिए हमेशा संभव है, जिसके परिणामस्वरूप एक ही मूल्य है। हालाँकि, जब वास्तविक दुनिया के अनुप्रयोगों के लिए पायथन का उपयोग करते हैं, तो आप जल्दी से कई मामलों में भाग लेते हैं जहां कई मानों को वापस करना आवश्यक होता है, और क्लीनर कोड में परिणाम होता है।

इसलिए, मैं कहूंगा कि जो कुछ भी समझ में आता है, और एक कृत्रिम सम्मेलन के अनुरूप होने की कोशिश न करें। अजगर कई वापसी मूल्यों का समर्थन करता है, इसलिए उचित होने पर इसका उपयोग करें।


4
अल्पविराम टपल, इसलिए अभिव्यक्ति बनाता है: q, r है एक टपल।
21

Vinko, एक उदाहरण है मानक पुस्तकालय से tempfile.mkstemp (), जो एक फ़ाइल हैंडल और एक पूर्ण पथ युक्त एक टपल लौटाता है। JFS, हाँ, आप सही हैं।
जेसन एथरिज

लेकिन यह एक ही उद्देश्य है ... आपके पास एक ही उद्देश्य और कई वापसी मूल्य हो सकते हैं
विंको व्रास्लोविक

यदि अन्य भाषाओं में कई रिटर्न प्रकार हो सकते हैं, तो मैं संदर्भों और 'आउट' मापदंडों के साथ नहीं अटकूंगा।
1

कई मूल्यों को वापस करना अजगर में सबसे बड़ी विशेषता है!
मार्टिन बेकेट

13

आप जो उदाहरण देते हैं, वह वास्तव में एक पायथन बिल्डिन फ़ंक्शन है, जिसे कहा जाता है divmod। तो किसी ने, किसी समय, सोचा था कि यह कोर कार्यक्षमता में शामिल करने के लिए पर्याप्त था।

मेरे लिए, यदि यह कोड को क्लीनर बनाता है, तो यह पायथोनिक है। इन दो कोड ब्लॉक की तुलना करें:

seconds = 1234
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)

seconds = 1234
minutes = seconds / 60
seconds = seconds % 60
hours = minutes / 60
minutes = minutes % 60

3

हां, कई मान लौटाना (यानी, टुपल) निश्चित रूप से पायथोनिक है। जैसा कि दूसरों ने बताया है, पायथन मानक पुस्तकालय में बहुत सारे उदाहरण हैं, साथ ही साथ अच्छी तरह से सम्मानित पायथन परियोजनाएं भी हैं। दो अतिरिक्त टिप्पणियां:

  1. कई मूल्यों को वापस करना कभी-कभी बहुत, बहुत उपयोगी होता है। उदाहरण के लिए, एक विधि जो वैकल्पिक रूप से एक घटना को संभालती है (ऐसा करने में कुछ मूल्य लौटाती है) और सफलता या विफलता भी लौटाती है। यह जिम्मेदारी पैटर्न की एक श्रृंखला में उत्पन्न हो सकती है। अन्य मामलों में, आप डेटा के कई, बारीकी से जुड़े टुकड़ों को वापस करना चाहते हैं --- जैसा कि दिए गए उदाहरण में है। इस सेटिंग में, कई मानों को लौटाना कई सदस्य चर के साथ एक अनाम वर्ग के एक ही उदाहरण को वापस करने के लिए समान है।
  2. पायथन की विधि संबंधी तर्कों को संभालने के लिए कई मूल्यों को सीधे लौटाने की क्षमता की आवश्यकता होती है। सी ++ में, उदाहरण के लिए, विधि तर्कों को संदर्भ द्वारा पारित किया जा सकता है, इसलिए आप औपचारिक रिटर्न मूल्य के अलावा, उन्हें आउटपुट मान निर्दिष्ट कर सकते हैं। पायथन में, तर्क "संदर्भ द्वारा" (लेकिन जावा के अर्थ में, C ++ नहीं) पारित किए जाते हैं। आप विधि तर्कों के लिए नए मान निर्दिष्ट नहीं कर सकते हैं और इसे विधि क्षेत्र के बाहर परिलक्षित करते हैं। उदाहरण के लिए:

    // C++
    void test(int& arg)
    {
        arg = 1;
    }
    
    int foo = 0;
    test(foo); // foo is now 1!
    

    तुलना करना:

    # Python
    def test(arg):
        arg = 1
    
    foo = 0
    test(foo) # foo is still 0
    

"एक विधि जो वैकल्पिक रूप से एक घटना को संभालती है और सफलता या विफलता भी लौटाती है" - यही अपवाद है।
नातान

यह बहुत व्यापक रूप से स्वीकार किया जाता है कि अपवाद केवल "असाधारण" स्थितियों के लिए हैं, केवल सफलता या विफलता के लिए नहीं। कुछ चर्चा के लिए Google "त्रुटि कोड बनाम अपवाद"।
zweiterlinde

1

यह निश्चित रूप से pythonic है। तथ्य यह है कि आप एक फ़ंक्शन से कई मानों को वापस कर सकते हैं बॉयलरप्लेट आपको सी जैसी भाषा में होगा जहां आपको हर प्रकार के संयोजन के लिए एक संरचना को परिभाषित करने की आवश्यकता होती है जो आप कहीं लौटते हैं।

हालाँकि, यदि आप उस बिंदु पर पहुँच जाते हैं जहाँ आप किसी एकल फ़ंक्शन से 10 मानों की तरह पागल हो रहे हैं, तो आपको गंभीरता से उन्हें एक वर्ग में बाँधने पर विचार करना चाहिए क्योंकि उस बिंदु पर यह अस्पष्ट है।



1

OT: RSRE के Algol68 में उत्सुक "/: =" ऑपरेटर है। जैसे।

INT quotient:=355, remainder;
remainder := (quotient /:= 113);

3 के भागफल और शेष 16 को देते हैं।

नोट: आम तौर पर "x (: / y =") के मान को "एक्स" के रूप में छोड़ दिया जाता है, जिसे संदर्भ द्वारा सौंपा गया है, लेकिन RSRE के मामले में लौटाया गया मान शेष है।

cf इंटेगर अरिथमेटिक - अल्गोल 68


0

साधारण कार्यों जैसे टपल के लिए कई मानों को वापस करना ठीक है divmod। यदि यह कोड को पठनीय बनाता है, तो यह पाइथोनिक है।

यदि रिटर्न मान भ्रमित होने लगे, तो जांचें कि क्या फ़ंक्शन बहुत अधिक कर रहा है और यदि यह है तो इसे विभाजित करें। यदि एक बड़े टपल का उपयोग वस्तु की तरह किया जा रहा है, तो इसे एक वस्तु बनाएं। इसके अलावा, नामित ट्यूपल्स का उपयोग करने पर विचार करें , जो पायथन 2.6 में मानक पुस्तकालय का हिस्सा होगा।


0

मैं पायथन के लिए काफी नया हूं, लेकिन टपल तकनीक मुझे बहुत ही अजीब लगती है। हालाँकि, मेरे पास एक और विचार है जो पठनीयता को बढ़ा सकता है। शब्दकोश का उपयोग करने से स्थिति के बजाय नाम से विभिन्न मूल्यों तक पहुंच की अनुमति मिलती है। उदाहरण के लिए:

def divide(x, y):
    return {'quotient': x/y, 'remainder':x%y }

answer = divide(22, 7)
print answer['quotient']
print answer['remainder']

2
यह मत करो। आप एक-लाइनर में परिणाम नहीं दे सकते हैं, यह बहुत ही स्पष्ट है। (जब तक आप परिणाम को संग्रहीत नहीं करना चाहते हैं, तो इस मामले में इसे एक विधि में रखना बेहतर है।) यदि आपके इरादे के साथ वापसी के मूल्यों को स्व-दस्तावेज करना है, तो) एएनएन को यथोचित व्याख्यात्मक नाम दें (जैसे " divmod ") और b) बाकी विवरण को एक डॉकस्ट्रिंग में डाल दिया (जो कि उन्हें लगाने के लिए पायथोनिक जगह है); अगर उस डॉकस्ट्रिंग को दो लाइनों से अधिक समय की आवश्यकता होती है, तो यह सुझाव देता है कि फ़ंक्शन को अत्यधिक लोड किया जा रहा है और यह एक बुरा विचार हो सकता है।
एसएमसीआई
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.