2010-01-18 20 views
13

अंदर kwargs जाओ अगर मैं ऐसा तरह एक अजगर समारोह है:समारोह

def some_func(arg1, arg2, arg3=1, arg4=2): 

यह तय करने के जो तर्क समारोह अंदर से कीवर्ड द्वारा पारित किए गए एक तरीका है?

संपादित

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

+1

मुझे ऐसा नहीं लगता ... फिर ** केडब्ल्यू के साथ परेशान क्यों होगा? – jldupont

+0

मुझे खेद है, लेकिन अगर यह सिर्फ आपकी जिज्ञासा है तो मैं बंद करने के लिए मतदान कर रहा हूं, कोई वास्तविक समस्या नहीं है, कोई उपयोग नहीं है, और किसी को कभी भी ऐसी समस्या नहीं होगी जिसके बारे में आप सपने देख रहे हैं। – SilentGhost

+0

असल में, मैं एक बार उस समस्या में भाग गया। मैं कुछ सीडीएटीए के आसपास एक एक्सएमएल रैपर उत्पन्न करने के लिए एक फ़ंक्शन लिख रहा था (एक स्टार्ट टैग प्रीपेड करें और एक एंड टैग संलग्न करें), और चाहता था कि यह 'def wrap (टैग, सामग्री = कोई नहीं, ** attrs) जैसा दिखता हो:' लेकिन फिर इस समस्या में आगे बढ़े कि गुणों में वर्ण हो सकते हैं कि पायथन पहचानकर्ता नहीं कर सकते हैं। लेकिन यह कुछ मिनटों के लिए एक दिलचस्प अभ्यास था। –

उत्तर

14

नहीं, इस हस्ताक्षर के साथ अजगर कोड में यह करने के लिए कोई रास्ता नहीं है - आप इस जानकारी की आवश्यकता है, तो आप समारोह के हस्ताक्षर बदलने की जरूरत है।

यदि आप पाइथन सी एपीआई देखते हैं, तो आप देखेंगे कि वास्तविक पायथन फ़ंक्शन को सामान्य पायथन फ़ंक्शन पर पारित किया जाता है, हमेशा एक टुपल प्लस एक ताना होता है - यानी, जिस तरह से हस्ताक्षर का प्रत्यक्ष प्रतिबिंब होता है *args, **kwargs का। उस टुपल और डॉक को तब विशिष्ट स्थितित्मक तर्कों में वर्णित किया जाता है और जिन्हें हस्ताक्षर में नामित किया जाता है, भले ही उन्हें नाम से पारित किया गया हो, और *a और **kw, यदि मौजूद है, तो केवल उस पार्सिंग से "ओवरफ्लो" लें, यदि कोई हो - केवल इस बिंदु पर आपका पायथन कोड नियंत्रण प्राप्त करता है, और तब तक आप जिस सूचना का अनुरोध कर रहे हैं (कैसे विभिन्न तर्क पारित किए गए थे) अब और आसपास नहीं है।

आपके द्वारा अनुरोधित जानकारी प्राप्त करने के लिए, इसलिए हस्ताक्षर को *a, **kw पर बदलें और अपना स्वयं का पार्सिंग/सत्यापन करें - यह "अंडा से आमलेट तक" जा रहा है, यानी एक निश्चित मात्रा में काम लेकिन निश्चित रूप से व्यवहार्य है, जबकि जो आप खोज रहे हैं वह "आमलेट से वापस अंडे तक" जा रहा है ... बस संभव नहीं है ;-)।

+0

+1: दिलचस्प समानता! – jldupont

+0

वास्तव में, मुझे भूख लगी :( – gorsky

1

क्या आप जानना चाहते हैं कि arg31 था क्योंकि यह बाहर से पारित किया गया था या क्योंकि यह डिफ़ॉल्ट मान था? जहां तक ​​मुझे पता है, ऐसा करने का कोई तरीका नहीं है। मुख्य कारण, मुझे संदेह है कि इस तरह के ज्ञान की कोई आवश्यकता नहीं है। क्या आम तौर पर किया जाता है निम्नलिखित है:

>>> def func(a, b=None): 
    if b is None: 
# here we know that function was called as: 
# func('spam') or func('spam', None) or func('spam', b=None) or func(a='spam', b=None) 

     b = 42 
1

बस इस तरह यह कार्य करें:

def some_func (arg1, arg2, arg3=None, arg4=None): 
    if arg3 is None: 
     arg3 = 1 # default value 
    if arg4 is None: 
     arg4 = 2 # default value 

    # do something 

इस तरह आप देख सकते हैं जब कुछ स्थापित किया गया था, और आप भी और अधिक जटिल डिफ़ॉल्ट ढांचे (सूचियों की तरह) के साथ काम करने में सक्षम हैं जैसी समस्याओं में चलने के बिना इन:

>>> def test(arg=[]): 
     arg.append(1) 
     print(arg) 
>>> test() 
[1] 
>>> test() 
[1, 1] 
+0

लेकिन आप अभी भी 'some_func (1, 2, none, 4)' और 'some_func (1, 2, arg4 = 4) 'के बीच अंतर नहीं बता सकते हैं। –

+1

आपको इसकी आवश्यकता क्यों होगी? नामांकित तर्क हैं ताकि आप अन्य वैकल्पिक पैरामीटर छोड़ सकें (इसलिए आपको उन सभी को लिखना नहीं है) – poke

+0

अच्छा, यही सवाल है, है ना? मार्क केवल वह व्यक्ति जो इसका जवाब दे सकता है। –

2

आप काफी अपने समारोह को फिर से परिभाषित करने के लिए जा रहे हैं:

def some_func(*args, **kwargs): 

और खुद को मार्शल करें। पास-दर-स्थिति, पास-बाय-कीवर्ड और डिफ़ॉल्ट के बीच अंतर बताने का कोई तरीका नहीं है।

9

यहाँ सज्जाकार के माध्यम से मेरे समाधान है:

def showargs(function): 
    def inner(*args, **kwargs): 
     return function((args, kwargs), *args, **kwargs) 
    return inner 

@showargs 
def some_func(info, arg1, arg2, arg3=1, arg4=2): 
    print arg1,arg2,arg3,arg4 
    return info 

In [226]: some_func(1,2,3, arg4=4) 
1 2 3 4 
Out[226]: ((1, 2, 3), {'arg4': 4}) 

एक तरह से यह आगे साफ करने के लिए हो सकता है, लेकिन यह मेरे लिए न्यूनतम दखल लगता है और फोन करने के कोड में कोई परिवर्तन नहीं की आवश्यकता है।

संपादित करें:

args, kwargs = info 
if 'arg4' in kwargs: 
    print "arg4 passed as keyword argument" 

अस्वीकरण:: वास्तव में परीक्षण करने के लिए करता है, तो विशेष रूप से आर्ग कीवर्ड द्वारा पारित किए गए, तो कुछ इस तरह करते हैं some_func के अंदर निम्नलिखित आप शायद विचार करना चाहिए या नहीं, आप सच में ध्यान तर्क कैसे पारित किए गए थे। यह पूरा दृष्टिकोण अनावश्यक हो सकता है।

+0

भी स्थानीय() मुझे लगता है –

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