2008-10-13 13 views
81

मैं .. उदाहरण के लिए .. एक dict, जो मैं कीवर्ड तर्कों के रूप कुंजी/मान पारित करने के लिए की जरूरत हैक्या आप पाइथन फ़ंक्शन प्राप्त करने वाले कीवर्ड तर्कों को सूचीबद्ध कर सकते हैं?

d_args = {'kw1': 'value1', 'kw2': 'value2'} 
example(**d_args) 

यह ठीक काम करता है, लेकिन अगर वहाँ d_args dict में मान जो स्वीकार नहीं कर रहे हैं example समारोह से, यह स्पष्ट रूप से मर जाता है .. कहो, अगर उदाहरण के समारोह def example(kw2):

के रूप में परिभाषित किया गया है यह एक समस्या है के बाद से मैं या तो d_args की पीढ़ी, या example समारोह को नियंत्रित नहीं करते .. वे दोनों आते हैं बाहरी मॉड्यूल से, और example केवल कुछ कीवर्ड-तर्कों को स्वीकार करता है ओम dict ..

आदर्श रूप में मैं सिर्फ

parsed_kwargs = feedparser.parse(the_url) 
valid_kwargs = get_valid_kwargs(parsed_kwargs, valid_for = PyRSS2Gen.RSS2) 
PyRSS2Gen.RSS2(**valid_kwargs) 

मैं शायद सिर्फ dict फिल्टर करेगा मान्य कीवर्ड-तर्कों की सूची से, क्या करना होगा, लेकिन मैं सोच रहा था: वहाँ एक रास्ता प्रोग्राम के लिए है किसी विशिष्ट फ़ंक्शन को ले जाने वाले कीवर्ड तर्कों को सूचीबद्ध करें?

उत्तर

114

एक छोटी सी कोड वस्तु सीधे निरीक्षण और चर बाहर काम करने से अच्छे निरीक्षण मॉड्यूल का उपयोग करने के लिए है।

>>> import inspect 
>>> def func(a,b,c=42, *args, **kwargs): pass 
>>> inspect.getargspec(func) 
(['a', 'b', 'c'], 'args', 'kwargs', (42,)) 

यदि आप जानना चाहते हैं कि यह किसी विशेष सेट के साथ कॉल करने योग्य है, तो आपको पहले से निर्दिष्ट डिफ़ॉल्ट के बिना तर्कों की आवश्यकता है।इन से मिला जा सकता है:

def getRequiredArgs(func): 
    args, varargs, varkw, defaults = inspect.getargspec(func) 
    if defaults: 
     args = args[:-len(defaults)] 
    return args # *args and **kwargs are not required, so ignore them. 

फिर एक समारोह में बताने के लिए है कि आप अपने विशेष dict से याद कर रहे हैं है:

def missingArgs(func, argdict): 
    return set(getRequiredArgs(func)).difference(argdict) 

इसी तरह, अवैध आर्ग के लिए जाँच करने के लिए, का उपयोग करें:

def invalidArgs(func, argdict): 
    args, varargs, varkw, defaults = inspect.getargspec(func) 
    if varkw: return set() # All accepted 
    return set(argdict) - set(args) 

और यदि कॉल करने योग्य है तो एक पूर्ण परीक्षण है:

def isCallableWithArgs(func, argdict): 
    return not missingArgs(func, argdict) and not invalidArgs(func, argdict) 

(यह केवल पायथन के तर्क पार्सिंग के रूप में अच्छा है। जाहिर है kwargs में अमान्य मान के लिए किसी भी क्रम चेकों का पता नहीं किया जा सकता है)

+0

अच्छा! मुझे यह काम नहीं पता था! – DzinX

+0

मुझे विश्वास है कि यह स्वीकार्य उत्तर होने का हकदार है। – codeape

+1

यह देखते हुए कि कोड ऑब्जेक्ट्स का उपयोग करने वाली विधि कम या समान समान है, क्या एक और मॉड्यूल आयात करने का कोई लाभ है ...? – jmetz

28

यह सब प्रचलित तर्क, कीवर्ड और गैर कीवर्ड लोगों के नाम प्रिंट होगा:

def func(one, two="value"): 
    y = one, two 
    return y 
print func.func_code.co_varnames[:func.func_code.co_argcount] 

यह वह जगह है पहले co_varnames हमेशा से रहे हैं क्योंकि मानकों (अगले स्थानीय चर, ऊपर के उदाहरण में y की तरह हैं)।

def getValidArgs(func, argsDict): 
    '''Return dictionary without invalid function arguments.''' 
    validArgs = func.func_code.co_varnames[:func.func_code.co_argcount] 
    return dict((key, value) for key, value in argsDict.iteritems() 
       if key in validArgs) 

जो तुम तो इस तरह इस्तेमाल कर सकते हैं:

>>> func(**getValidArgs(func, args)) 

संपादित:

तो अब आप एक समारोह हो सकता था एक छोटा सा अतिरिक्त: अगर आप वास्तव में जरूरत है फ़ंक्शन के केवल कीवर्ड तर्क, आप उन्हें निकालने के लिए func_defaults विशेषता का उपयोग कर सकते हैं:

def getValidKwargs(func, argsDict): 
    validArgs = func.func_code.co_varnames[:func.func_code.co_argcount] 
    kwargsLen = len(func.func_defaults) # number of keyword arguments 
    validKwargs = validArgs[-kwargsLen:] # because kwargs are last 
    return dict((key, value) for key, value in argsDict.iteritems() 
       if key in validKwargs) 

अब आप ज्ञात आर्ग के साथ अपने समारोह, लेकिन निकाले kwargs, उदा .:

func(param1, param2, **getValidKwargs(func, kwargsDict)) 

कह सकते हैं मतलब यह है कि func उसके हस्ताक्षर में कोई *args या **kwargs जादू का उपयोग करता है।

3

DzinX के जवाब का विस्तार:

argnames = example.func_code.co_varnames[:func.func_code.co_argcount] 
args = dict((key, val) for key,val in d_args.iteritems() if key in argnames) 
example(**args) 
6

अजगर 3.0 में:।

>>> import inspect 
>>> import fileinput 
>>> print(inspect.getfullargspec(fileinput.input)) 
FullArgSpec(args=['files', 'inplace', 'backup', 'bufsize', 'mode', 'openhook'], 
varargs=None, varkw=None, defaults=(None, 0, '', 0, 'r', None), kwonlyargs=[], 
kwdefaults=None, annotations={}) 
0

एक अजगर 3 समाधान के लिए, आप the kind of parameters के अनुसार आप चाहें inspect.signature और फिल्टर का उपयोग कर सकते के बारे में पता करने के लिए।

स्थितीय या कीवर्ड, केवल कीवर्ड वाला, वर स्थितीय और वर कीवर्ड मानकों के साथ एक नमूना समारोह ले रहा है:

def spam(a, b=1, *args, c=2, **kwargs): 
    print(a, b, args, c, kwargs) 

आप इसके लिए एक हस्ताक्षर वस्तु बना सकते हैं:

from inspect import signature 
sig = signature(spam) 

और फिर से फिल्टर आपको आवश्यक विवरणों को जानने के लिए एक सूची समझ के साथ:

>>> # positional or keyword 
>>> [p.name for p in sig.parameters.values() if p.kind == p.POSITIONAL_OR_KEYWORD] 
['a', 'b'] 
>>> # keyword only 
>>> [p.name for p in sig.parameters.values() if p.kind == p.KEYWORD_ONLY] 
['c'] 

और, इसी प्रकार, p.VAR_POSITIONAL और VAR_KEYWORD के साथ var कीवर्ड का उपयोग कर var positionals के लिए।

इसके अलावा, यदि आप p.defaultp.empty के बराबर जांचते हैं तो यह जांचने के लिए कि कोई डिफ़ॉल्ट मान मौजूद है या नहीं, तो आप एक खंड जोड़ सकते हैं।

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

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