16

अजगर में, यह करने के लिए बेहतर शैली माना जाता है:अजगर में, आंशिक समारोह आवेदन (currying) बनाम स्पष्ट फ़ंक्शन परिभाषा

  • स्पष्ट रूप से अधिक सामान्य, संभवतः आंतरिक उपयोग, कार्य के संदर्भ में उपयोगी कार्यों को परिभाषित; या,
  • फ़ंक्शन करीइंग का स्पष्ट रूप से वर्णन करने के लिए आंशिक फ़ंक्शन एप्लिकेशन का उपयोग करें?

मैं एक प्रश्न के उदाहरण के माध्यम से अपने प्रश्न की व्याख्या करूंगा।

मान लीजिए कि कोई एक फ़ंक्शन लिखता है, _sort_by_scoring, जिसमें दो तर्क होते हैं: एक स्कोरिंग फ़ंक्शन और आइटम की एक सूची। यह मूल सूची में प्रत्येक आइटम की स्थिति के आधार पर स्कोर द्वारा क्रमबद्ध मूल सूची की एक प्रति देता है। दो उदाहरण स्कोरिंग फ़ंक्शंस भी प्रदान किए जाते हैं।

def _sort_by_score(scoring, items_list): 
    unsorted_scored_list = [(scoring(len(items_list), item_position), item) for item_position, item in enumerate(items_list)] 
    sorted_list = [item for score, item in sorted(unsorted_scored_list)] 
    return sorted_list 

def _identity_scoring(items_list_size, item_position): 
    return item_position 

def _reversed_scoring(items_list_size, item_position): 
    return items_list_size - item_position 

फ़ंक्शन _sort_by_score को सीधे कभी नहीं कहा जाता है; इसके बजाए, इसे अन्य सिंगल-तर्क फ़ंक्शंस द्वारा बुलाया जाता है जो स्कोरिंग फ़ंक्शन और उनके अकेले तर्क (आइटम्स की एक सूची) को _sort_by_scoring पर पास करते हैं और परिणाम लौटाते हैं।

# Explicit function definition style 
def identity_ordering(items_list): 
    return _sort_by_score(_identity_scoring, items_list) 

def reversed_ordering(items_list): 
    return _sort_by_score(_reversed_scoring, items_list) 

जाहिर है, यह इरादा फ़ंक्शन करी के संदर्भ में बेहतर व्यक्त किया गया है। (या तो मामले में)

# Curried function definition style 
import functools 
identity_ordering = functools.partial(_sort_by_score, _identity_scoring) 
reversed_ordering = functools.partial(_sort_by_score, _reversed_scoring) 

उपयोग:

>>> foo = [1, 2, 3, 4, 5] 
>>> identity_ordering(foo) 
[1, 2, 3, 4, 5] 
>>> reversed_ordering(foo) 
[5, 4, 3, 2, 1] 

स्पष्ट फ़ंक्शन परिभाषा शैली का स्पष्ट फायदे:

  1. उपयोगी कार्यों अधिक सामान्य कार्य हैं से पहले परिभाषित किया जा सकता है, को ऊपर उठाने के बिना NameErrors;
  2. सहायक फ़ंक्शन (उदा।, फ़ोरिंग फ़ंक्शन) फ़ंक्शन परिभाषा निकाय के भीतर परिभाषित किया जा सकता है;
  3. संभवतः डीबग करना आसान है;
  4. कोड "स्पष्ट से स्पष्ट स्पष्ट है" के आधार पर अच्छा लग रहा है।

curried समारोह परिभाषा शैली का स्पष्ट फायदे:

  1. कार्यात्मक प्रोग्रामिंग मुहावरे के इरादे को व्यक्त करता है;
  2. कोड संक्षिप्तता के आधार पर अच्छा लग रहा है।

"उपयोगी" फ़ंक्शंस को परिभाषित करने के लिए, दोनों शैलियों में से किस को प्राथमिकता दी जाती है? क्या ऐसी अन्य शैलियों हैं जो अधिक बेवकूफ/पायथनिक/आदि हैं?

+3

एक, currying और आंशिक आवेदन दो हैं: इस प्रकार, आप भी निम्न कार्यान्वयन का उपयोग कर सकते अलग अलग बातें। करीबी कार्य एक समय में एक तर्क को काम करने के लिए फ़ंक्शन को बदलने का तात्पर्य है। तो जब आप पहली तर्क लागू करते हैं तो आपको एक समारोह मिलता है तो आप दूसरा तर्क लागू कर सकते हैं। आंशिक अनुप्रयोग फ़ंक्शन आमंत्रण – PuercoPop

उत्तर

13

यदि आप सार्वजनिक इंटरफ़ेस के हिस्से के रूप में करीबी कार्य करना चाहते हैं, तो स्पष्ट फ़ंक्शन परिभाषाओं का उपयोग करें। इसमें निम्नलिखित अतिरिक्त फायदे हैं:

  1. एक स्पष्ट फ़ंक्शन परिभाषा के लिए डॉकस्ट्रिंग असाइन करना आसान है। partial() फ़ंक्शंस के लिए, आपको __doc__ विशेषता को असाइन करना होगा, जो कुछ हद तक बदसूरत है।

  2. मॉड्यूल स्रोत ब्राउज़ करते समय वास्तविक फ़ंक्शन परिभाषाओं को स्किम करना आसान होता है।

मैं functools.partial() एक समान तरीके से लैम्ब्डा भाव यानी स्थानीय स्तर पर की जरूरत थ्रो-दूर कार्यों के लिए उपयोग करते हैं, करेंगे।

अपने विशिष्ट उदाहरण में, मैं शायद का उपयोग करेंगे न, ड्रॉप प्रमुख अंडरस्कोर और

sort_by_score(identity_scoring, foo) 

जो मेरे लिए सबसे स्पष्ट लगता है कहते हैं।

+0

पर कुछ पैरामीटर को ठीक कर रहा है और ... मैं अपना जवाब छोड़ सकता हूं, क्योंकि स्वेन ने मुझे इसे हराया :) – ncoghlan

+1

@ncoghlan: क्या हमने दो दिन पहले कुछ इसी तरह चर्चा नहीं की थी? :) –

+0

सहमत! धन्यवाद। –

2

मामूली स्पर्शरेखा के रूप में, आमतौर पर sorted बिल्टिन को सजावटी-तरह-अनावश्यक काम को व्यावहारिक रूप में करने के लिए वांछनीय है। उदाहरण के लिए:

def _sort_by_score(scoring, items_list): 
    num_items = len(items_list) 
    def score(entry): 
     return scoring(num_items, entry[0]) 
    return [item for position, item in sorted(enumerate(items_list), key=score)] 

(एक जवाब क्योंकि कोड के ब्लॉक टिप्पणी के रूप में काम नहीं करते के रूप में केवल पोस्ट वास्तविक प्रश्न पूछा करने के लिए एक जवाब के लिए स्वेन की प्रतिक्रिया देखें।)

संपादित किसी और द्वारा: पायथन सॉर्ट फ़ंक्शन सूची के माध्यम से पुनरावृत्त करता है और पहले कुंजी की सूची उत्पन्न करता है। इनपुट सूची के क्रम में key() फ़ंक्शन को प्रत्येक सूची आइटम के लिए केवल एक बार बुलाया जाता है।

def _sort_by_score(scoring, items_list): 
    num_items = len(items_list) 
    index = itertools.count() 
    def score(entry): 
     return scoring(num_items, next(index)) 
    return sorted(items_list, key=score) 

एक तरफ ध्यान दें (केवल एक संशोधन के रूप में तैनात है क्योंकि कोड के ब्लॉक टिप्पणी के रूप में काम नहीं करते।)

+0

यह निश्चित रूप से अधिक सुरुचिपूर्ण है। हालांकि, मेरे पास एक और सामान्य मामला है जिसमें _sort_by_score आइटम्स_लिस्ट (जिसे piles_list कहा जाता है) की सूची पर संचालित होता है, और इसी स्कोरिंग फ़ंक्शन में चार तर्क होते हैं: piles_list_size, pile_position, items_list_size, आइटम स्थिति। यह मेरे लिए स्पष्ट नहीं है कि इस मामले में कुंजी के साथ क्रमबद्ध कैसे उपयोग करें। शायद यह एक और समय के लिए एक सवाल है। =) आपकी अंतर्दृष्टि के लिए धन्यवाद! –

+0

@ सेवन: दिलचस्प चाल, मैंने कभी सोचा नहीं! अब मैं सोच रहा हूं कि भाषा परिभाषा उस व्यवहार की गारंटी देती है ... – ncoghlan

+1

[सॉर्ट किए गए दस्तावेज] (http://docs.python.org/library/functions.html#sorted) कम से कम कहता है कि मुख्य फ़ंक्शन को कॉल किया जाता है प्रति आइटम केवल एक बार। चूंकि इसे वास्तविक सॉर्टिंग से पहले किया जाना है, इसलिए मैं कल्पना नहीं कर सकता कि यह कभी कैसे बदल सकता है, लेकिन निश्चित रूप से कोई गारंटी नहीं है। –

संबंधित मुद्दे