116

キー/値をキーワード引数として渡す必要があるdictがあります..たとえば..

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

これは正常に動作します、関数によって受け入れられない値が d_args dict にあるexample場合、明らかに死にます..例の関数が次のように定義されているとします。def example(kw2):

d_args、または関数の生成を制御していないため、これは問題exampleです。これらは両方とも外部モジュールexampleから取得され、辞書からのキーワード引数の一部のみを受け入れます。

理想的には私はただするだろう

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

おそらく、有効なキーワード引数のリストからdictをフィルタリングするだけですが、疑問に思っていました:特定の関数が取るキーワード引数をプログラムでリストする方法はありますか?

4

6 に答える 6

162

コード オブジェクトを直接検査して変数を処理するよりも、inspect モジュールを使用する方が少し便利です。

>>> 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.

次に、特定の辞書から何が欠けているかを伝える関数は次のとおりです。

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)

(これは、python の arg 解析に関してのみ有効です。実行時に kwargs の無効な値をチェックしても、明らかに検出できません。)

于 2008-10-13T09:02:23.973 に答える
33

これにより、すべての通過可能な引数、キーワードおよび非キーワードの引数の名前が出力されます。

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これは、署名にno*argsまたは**kwargsmagicが使用されていることを前提としています。

于 2008-10-13T08:09:15.390 に答える
9

Python 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={})
于 2008-10-13T09:32:56.580 に答える
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)
于 2008-10-13T08:20:20.657 に答える