2010-06-03 10 views
42

में पैरामीटर के नामकरण मजबूर अजगर में आप एक समारोह परिभाषा हो सकता है:अजगर

def info(object, spacing=10, collapse=1) 

जो निम्न तरीकों में से किसी में कहा जा सकता है:

info(odbchelper)      
info(odbchelper, 12)     
info(odbchelper, collapse=0)   
info(spacing=15, object=odbchelper) 

है- की अनुमति देता है पायथन के लिए धन्यवाद ऑर्डर तर्क, जब तक उनका नाम दिया गया हो।

हमारे पास होने वाली समस्या हमारे कुछ बड़े कार्यों के बढ़ने के कारण है, लोग spacing और collapse के बीच पैरामीटर जोड़ सकते हैं, जिसका अर्थ है कि गलत मान पैरामीटर पर जा रहे हैं जिनका नाम नहीं है। इसके अलावा कभी-कभी यह हमेशा स्पष्ट नहीं होता है कि इसमें क्या जाना है। हम लोगों को कुछ पैरामीटर नाम देने के लिए मजबूर करने के तरीके के बाद हैं - न सिर्फ एक कोडिंग मानक, बल्कि आदर्श रूप से ध्वज या पीडीडीवी प्लगइन?

ताकि उपर्युक्त 4 उदाहरणों में, केवल आखिरी बार चेक पास हो जाए क्योंकि सभी पैरामीटर नामित हैं।

बाधाएं हम केवल कुछ कार्यों के लिए इसे चालू कर देंगे, लेकिन इसे लागू करने के तरीके के बारे में कोई सुझाव - या यदि यह भी संभव है तो इसकी सराहना की जाएगी।

उत्तर

94

पायथन 3 - हां में, आप तर्क सूची में * निर्दिष्ट कर सकते हैं।

"*" या "* पहचानकर्ता" के बाद पैरामीटर कीवर्ड-केवल पैरामीटर हैं और केवल कीवर्ड तर्कों का उपयोग किया जा सकता है।

नमूना कोड (from python ref):

>>> def foo(pos, *, forcenamed): 
... print(pos, forcenamed) 
... 
>>> foo(pos=10, forcenamed=20) 
10 20 
>>> foo(10, forcenamed=20) 
10 20 
>>> foo(10, 20) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: foo() takes exactly 1 positional argument (2 given) 
+4

लोग अपने उद्धरण के स्रोत की तलाश में हैं, यह पाइथन 3 डॉक्स में है: https://docs.python.org/3.5/reference/compound_stmts.html#function-definitions – phoenix

+0

** kwargs के साथ: 'def foo (pos, *, forcenamed, ** kwargs) '। – Jerther

0

आप ** ऑपरेटर इस्तेमाल कर सकते हैं:

def info(**kwargs): 

इस तरह से लोगों को नामित पैरामीटर का उपयोग करने के लिए मजबूर कर रहे हैं।

+0

और आपको पता नहीं है कि आपके कोड को पढ़ने के बिना अपनी विधि को कैसे कॉल करें, अपने उपभोक्ता पर संज्ञानात्मक भार बढ़ाना :( – Dagrooms

1

आप अपने कार्यों को केवल **args प्राप्त करने के रूप में घोषित कर सकते हैं। उस कीवर्ड तर्क यह आदेश निहित है लेकिन आप कुछ अतिरिक्त काम यकीन ही मान्य नाम में पारित कर रहे हैं बनाने के लिए होगा

def foo(**args): 
    print args 

foo(1,2) # Raises TypeError: foo() takes exactly 0 arguments (2 given) 
foo(hello = 1, goodbye = 2) # Works fine. 
+0

न केवल आपको कीवर्ड चेक जोड़ना है, बल्कि एक उपभोक्ता के बारे में सोचें जो जानता है कि उन्हें एक विधि कॉल करना है हस्ताक्षर 'foo (** kwargs)'। मैं उसमें क्या पास करूं? 'foo (killme = True, when = "rightnowplease") ' – Dagrooms

+0

यह वास्तव में निर्भर करता है।' dict'। –

2

अद्यतन:।

मैंने महसूस किया कि **kwargs का उपयोग कर समस्या का समाधान नहीं होगा। अपने प्रोग्रामर समारोह तर्क को बदलते हैं के रूप में वे चाहते हैं, तो एक उदाहरण के लिए, समारोह इस के लिए बदल सकता है:

def info(foo, **kwargs): 

और (क्योंकि अब हर कार्य कॉल पहला तर्क शामिल करने के लिए है) पुराने कोड फिर से टूट जाएगा।

यह वास्तव में ब्रायन के कहने के लिए नीचे आता है।


(...) लोगों spacing और collapse (...)

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

(...) कभी कभी यह हमेशा क्या में जाने की जरूरत है के रूप में स्पष्ट नहीं है।

समारोह के हस्ताक्षर को देख कर (यानी def info(object, spacing=10, collapse=1)) एक तुरंत देखना चाहिए कि हर तर्क डिफ़ॉल्ट मान है कि नहीं, अनिवार्य है।
तर्क है, डॉकस्ट्रिंग में जाना चाहिए।


पुराना जवाब (पूर्णता के लिए रखा):

आप कार्यों को इस तरह परिभाषित कर सकते हैं:

def info(**kwargs): 
    ''' Some docstring here describing possible and mandatory arguments. ''' 
    spacing = kwargs.get('spacing', 15) 
    obj = kwargs.get('object', None) 
    if not obj: 
     raise ValueError('object is needed') 

kwargs

यह शायद एक अच्छा समाधान नहीं है एक शब्दकोश है जिसमें कोई कीवर्ड तर्क शामिल है। आप जांच सकते हैं कि एक अनिवार्य तर्क मौजूद है और यदि नहीं, तो अपवाद उठाएं।

नकारात्मकता यह है कि यह अब स्पष्ट नहीं हो सकता है, जो तर्क संभव हैं, लेकिन उचित डॉकस्ट्रिंग के साथ, यह ठीक होना चाहिए।

+3

पर विचार करें, मुझे आपका पुराना उत्तर बेहतर पसंद आया। बस एक टिप्पणी दें कि आप केवल फ़ंक्शन में ** kwargs क्यों स्वीकार कर रहे हैं। आखिरकार, कोई भी स्रोत कोड में कुछ भी बदल सकता है - आपको अपने निर्णयों के पीछे इरादे और उद्देश्य का वर्णन करने के लिए दस्तावेज़ की आवश्यकता है। – Brandon

0
def cheeseshop(kind, *arguments, **keywords): 
अजगर में

अगर उपयोग * args आप इस पैरामीटर के लिए तर्कों की एन-नंबर पारित कर सकते हैं इसका मतलब है कि - जो

और उपयोग करता है, तो उपयोग करने के लिए समारोह के अंदर एक सूची आने दिया जाएगा * * केडब्ल्यू जिसका अर्थ है कि इसका कीवर्ड तर्क है, जिसे dict के रूप में एक्सेस किया जा सकता है - आप केडब्ल्यू तर्कों की संख्या को पास कर सकते हैं, और यदि आप उस उपयोगकर्ता को प्रतिबंधित करना चाहते हैं तो क्रम में अनुक्रम और तर्क दर्ज करना होगा, फिर * और ** का उपयोग न करें - (बड़े वास्तुकला के लिए सामान्य समाधान प्रदान करने के लिए इसका पायथन तरीका ...)

यदि आप मूलभूत मूल्यों के साथ अपने समारोह प्रतिबंधित करना चाहते हैं तो आप जाँच कर सकते हैं अंदर यह

def info(object, spacing, collapse) 
    spacing = spacing or 10 
    collapse = collapse or 1 
0

अन्य उत्तर कहना के रूप में, समारोह हस्ताक्षर बदलते एक बुरा विचार है। या तो अंत में नए पैरामीटर जोड़ें, या तर्कों को डालने पर प्रत्येक कॉलर को ठीक करें।

यदि आप अभी भी ऐसा करना चाहते हैं, तो function decorator और inspect.getargspec फ़ंक्शन का उपयोग करें। यह कुछ इस तरह इस्तेमाल किया जाएगा:

@require_named_args 
def info(object, spacing=10, collapse=1): 
    .... 

require_named_args का कार्यान्वयन पाठक के लिए एक व्यायाम के रूप में छोड़ दिया जाता है।

मुझे परेशान नहीं होगा। जब भी फ़ंक्शन कहा जाता है तो यह धीमा हो जाएगा, और आपको कोड को अधिक ध्यान से लिखने से बेहतर परिणाम मिलेंगे।

-2

मुझे नहीं पता कि एक प्रोग्रामर पहले स्थान पर दो अन्य लोगों के बीच पैरामीटर जोड़ देगा।

यदि आप फ़ंक्शन पैरामीटर को नामों के साथ उपयोग करना चाहते हैं (उदा। info(spacing=15, object=odbchelper)) तो इससे कोई फ़र्क नहीं पड़ता कि उन्हें किस क्रम में परिभाषित किया गया है, ताकि आप अंत में नए पैरामीटर भी डाल सकें।

यदि आप मामले को ध्यान में रखना चाहते हैं तो आप इसे बदलने के लिए कुछ भी काम करने की उम्मीद नहीं कर सकते हैं!

+0

यह प्रश्न का उत्तर नहीं देता है चाहे यह एक अच्छा विचार है या नहीं, अप्रासंगिक है - कोई भी इसे वैसे भी कर सकता है। –

+0

जैसा कि ग्रीम ने उल्लेख किया है, कोई भी वैसे भी करेगा। इसके अलावा, यदि आप दूसरों द्वारा उपयोग की जाने वाली लाइब्रेरी लिख रहे हैं, तो केवल कीवर्ड के उत्तीर्ण (केवल पायथन 3) को छोड़कर केवल तर्क आपके अतिरिक्त एपीआई को दोबारा करने के लिए अतिरिक्त लचीलापन की अनुमति देता है। – s0undt3ch

14

आप लोगों को निम्नलिखित तरीकों से एक फ़ंक्शन को परिभाषित करके Python3 में कीवर्ड तर्कों का उपयोग करने के लिए मजबूर कर सकते हैं।

def foo(*, arg0="default0", arg1="default1", arg2="default2"): 
    pass 

कोई नाम नहीं आप हर किसी को समारोह कीवर्ड तर्क का उपयोग करने के जो है मैं क्या लगता है कि आप के बारे में पूछ रहे थे कॉल बल के साथ पहला तर्क एक स्थितीय तर्क करके। को Python2 में यह करने के लिए एक ही रास्ता इस

def foo(**kwargs): 
    pass 

की तरह एक समारोह को परिभाषित करने कि kwargs उपयोग करने के लिए फोन करने वाले के लिए मजबूर कर देंगे है, लेकिन यह है कि एक समाधान के महान आप तो एक डाल करने के लिए होगा के रूप में नहीं है आपको जिस तर्क की आवश्यकता है उसे स्वीकार करने के लिए जांचें।

7

यह सच है, सबसे प्रोग्रामिंग भाषाओं मेकअप समारोह कॉल अनुबंध के पैरामीटर के क्रम हिस्सा है, लेकिन इस की जरूरत नहीं है तो हो सकता है। यह क्यों होगा सवाल की मेरी समझ तब है, यदि पाइथन इस संबंध में अन्य प्रोग्रामिंग भाषाओं के लिए अलग है।

__named_only_start = object() 

def info(param1,param2,param3,_p=__named_only_start,spacing=10,collapse=1): 
    if _p is not __named_only_start: 
     raise TypeError("info() takes at most 3 positional arguments") 
    return str(param1+param2+param3) +"-"+ str(spacing) +"-"+ str(collapse) 

एक ही तरीका है एक फोन करने वाले positionally (एक अपवाद के बिना) तर्क spacing और collapse प्रदान करने में सक्षम हो जाएगा होगा:: अजगर 2 के लिए अन्य अच्छे जवाब के अलावा, निम्नलिखित पर विचार करें

info(arg1, arg2, arg3, module.__named_only_start, 11, 2) 

अन्य मॉड्यूल से संबंधित निजी तत्वों का उपयोग न करने का सम्मेलन पाइथन में पहले से ही बहुत बुनियादी है। पाइथन के साथ ही, पैरामीटर के लिए यह सम्मेलन केवल अर्द्ध-लागू होगा।

अन्यथा, कॉल इस रूप में होने की आवश्यकता होगी:

info(arg1, arg2, arg3, spacing=11, collapse=2) 

एक कॉल

info(arg1, arg2, arg3, 11, 2) 

आवंटित होगा मूल्य 11 पैरामीटर के लिए _p और एक अपवाद समारोह की पहली अनुदेश द्वारा बढ़ी।

विशेषताएं:

  • पैरामीटर से पहले _p=__named_only_start positionally (नाम से या) में भर्ती कराया गया है।
  • _p=__named_only_start के बाद पैरामीटर केवल नाम से प्रदान किए जाने चाहिए (जब तक कि विशेष सेंटीनल ऑब्जेक्ट __named_only_start प्राप्त नहीं किया जाता है) उपयोग किया जाता है और उपयोग किया जाता है)।

सकारात्मक:

  • पैरामीटर संख्या और अर्थ (बाद में अगर अच्छा नाम भी चुना जाता है, ज़ाहिर है,) में स्पष्ट कर रहे हैं।
  • यदि सेंटीनेल को पहले पैरामीटर के रूप में निर्दिष्ट किया गया है, तो सभी तर्कों को नाम से निर्दिष्ट करने की आवश्यकता है।
  • फ़ंक्शन को कॉल करते समय, संबंधित स्थिति में सेंटीनेल ऑब्जेक्ट __named_only_start का उपयोग कर स्थितित्मक मोड पर स्विच करना संभव है।
  • अन्य विकल्पों की तुलना में बेहतर प्रदर्शन की उम्मीद की जा सकती है।

विपक्ष:

  • जाँच चलाने के समय के दौरान होता है, संकलन-समय पर नहीं।
  • अतिरिक्त पैरामीटर (हालांकि तर्क नहीं) और अतिरिक्त चेक का उपयोग करें। नियमित कार्यों के लिए छोटे प्रदर्शन गिरावट सम्मान।
  • कार्यक्षमता भाषा द्वारा प्रत्यक्ष समर्थन के बिना एक हैक है (नीचे नोट देखें)।
  • फ़ंक्शन को कॉल करते समय, सही स्थिति में सेंटीनेल ऑब्जेक्ट __named_only_start का उपयोग कर स्थितित्मक मोड पर स्विच करना संभव है। हां, इसे प्रो के रूप में भी देखा जा सकता है।

कृपया ध्यान रखें कि यह उत्तर केवल पायथन 2 के लिए मान्य है। पायथन 3 समान उत्तरों, लेकिन बहुत ही सुरुचिपूर्ण, भाषा-समर्थित तंत्र को अन्य उत्तरों में वर्णित करता है।

मुझे पता चला है कि जब मैं अपना दिमाग खोलता हूं और इसके बारे में सोचता हूं, कोई प्रश्न या अन्य का निर्णय बेवकूफ, गूंगा या मूर्खतापूर्ण लगता है। इसके विपरीत: मैं आमतौर पर बहुत कुछ सीखता हूं।

+0

_ "रनिंग समय के दौरान जांच होती है, संकलन-समय नहीं।" _ - मुझे लगता है कि यह सभी फ़ंक्शन तर्क जांच के बारे में सच है। जब तक आप वास्तव में फ़ंक्शन आमंत्रण की रेखा निष्पादित नहीं करते हैं, तब तक आप हमेशा नहीं जानते कि कौन सा फ़ंक्शन निष्पादित किया जा रहा है। इसके अलावा, ** + 1 ** - यह चालाक है। – Eric

+0

@Eric: यह सिर्फ इतना है कि मैंने स्थैतिक जांच को प्राथमिकता दी होगी। लेकिन आप सही हैं: वह बिल्कुल पाइथन नहीं होता। हालांकि एक निर्णायक बिंदु नहीं है, पाइथन 3 का "*" निर्माण भी गतिशील रूप से चेक किया गया है। आपके कमेंट के लिए धन्यवाद। –

+0

इसके अलावा, यदि आप मॉड्यूल चर '_name_only_start' नाम करते हैं, तो इसे बाहरी मॉड्यूल से संदर्भित करना असंभव हो जाता है, जो प्रो और कॉन लेता है। (मॉड्यूल स्कोप पर एकल अग्रणी अंडरस्कोर निजी हैं, आईआईआरसी) – Eric

2

आप एक तरह से कि दोनों अजगर 2 और अजगर 3 में काम करता है, एक "फर्जी" पहले कीवर्ड एक डिफ़ॉल्ट मान है कि "स्वाभाविक रूप से" घटित नहीं होगा साथ तर्क करके में ऐसा कर सकते हैं। उस कीवर्ड तर्क मूल्य के बिना एक या अधिक तर्क से पहले आना कर सकते हैं:

_dummy = object() 

def info(object, _kw=_dummy, spacing=10, collapse=1): 
    if _kw is not _dummy: 
     raise TypeError("info() takes 1 positional argument but at least 2 were given") 

यह अनुमति देगा:

info(odbchelper)   
info(odbchelper, collapse=0)   
info(spacing=15, object=odbchelper) 

लेकिन नहीं:

info(odbchelper, 12)     

आप के लिए समारोह को बदलते हैं:

def info(_kw=_dummy, spacing=10, collapse=1): 

तो सभी तर्कों में कीवर्ड होना चाहिए और info(odbchelper) अब काम नहीं करेगा।

यह आपको _kw के बाद किसी भी स्थान पर अतिरिक्त कीवर्ड तर्कों को रखने की अनुमति देगा, बिना अंतिम प्रविष्टि के बाद उन्हें रखने के लिए मजबूर किए बिना। यह अक्सर समझ में आता है, उदा। तर्कसंगत रूप से समूहीकृत या व्यवस्थित कीवर्ड की व्यवस्था करना रखरखाव और विकास में सहायता कर सकता है।

इसलिए def(**kwargs) का उपयोग करने और अपने स्मार्ट संपादक में हस्ताक्षर जानकारी खोने की कोई आवश्यकता नहीं है।आपका सामाजिक अनुबंध कुछ जानकारी प्रदान करना है, उनमें से कुछ को मजबूर करना (उनमें से कुछ) को कीवर्ड की आवश्यकता है, इन आदेशों को प्रस्तुत किया गया है, यह अप्रासंगिक हो गया है।