Kan du liste opp nøkkelordargumenter en funksjon mottar?

stemmer
86

Jeg har en dict, som jeg må passere nøkkel / verdi som søkeord argumenter .. For eksempel ..

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

Dette fungerer greit, men hvis det er verdier i d_args dict som ikke er akseptert av examplefunksjon, det åpenbart dør .. Si hvis eksemplet funksjon er definert somdef example(kw2):

Dette er et problem siden jeg ikke kontrollerer enten generering av d_args, eller examplefunksjon .. Begge kommer fra eksterne moduler, og examplebare godtar noen av søkeord-argumentene fra dict ..

Ideelt sett ville jeg bare gjøre

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

Jeg vil sannsynligvis bare filtrere dict, fra en liste over gyldige søkeord-argumenter, men jeg lurte på: Er det en måte å auto liste søkeord argumentene de en bestemt funksjon tar?

Publisert på 13/10/2008 klokken 07:55
kilden bruker
På andre språk...                            


5 svar

stemmer
28

Dette vil skrive navnene på alle farbar argumenter, søkeord og ikke-søkeord seg:

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

Dette er fordi første co_varnamesalltid er parametrer (neste er lokale variabler, slik som yi eksempelet ovenfor).

Så nå kan du ha en funksjon:

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)

Som du deretter kan bruke som dette:

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

EDIT : En liten tillegg: Hvis du egentlig bare trenger søkeord argumenter for en funksjon, kan du bruke func_defaultsattributtet for å pakke dem:

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)

Du kan nå ringe funksjon med kjente args, men hentet kwargs, for eksempel:

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

Dette forutsetter at funcbruker ingen *argseller **kwargsmagi i sin signatur.

Svarte 13/10/2008 kl. 08:09
kilden bruker

stemmer
3

Utvide DzinX svar:

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)
Svarte 13/10/2008 kl. 08:20
kilden bruker

stemmer
119

Litt bedre enn å inspisere koden objektet direkte og arbeider ut variablene er å bruke inspisere modulen.

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

Hvis du ønsker å vite om det er callable med et bestemt sett av args, trenger du args uten en standard som allerede er angitt. Disse kan være fikk etter:

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.

Deretter en funksjon for å fortelle hva du mangler fra din spesielle dict er:

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

Tilsvarende for å se etter ugyldige args, bruke:

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

Og så en full test på om det er callable er:

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

(Dette er bra bare så langt som Pythons arg analyse. Ikke kan oppdages Eventuelle kjøretids sjekker for ugyldige verdier i kwargs åpenbart.)

Svarte 13/10/2008 kl. 09:02
kilden bruker

stemmer
6

I 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={})
Svarte 13/10/2008 kl. 09:32
kilden bruker

stemmer
2

For en Python 3 løsning, kan du bruke inspect.signatureog filter i henhold til hva slags parametere du ønsker å vite om.

Å ta en prøve funksjon med posisjons eller nøkkelord, nøkkelord-kun, Var posisjonelle og Var søkeparametere:

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

Du kan lage en signatur objekt for det:

from inspect import signature
sig =  signature(spam)

og deretter filtrere med en liste forståelse for å finne ut detaljene du trenger:

>>> # 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']

og tilsvarende for Var positionals hjelp p.VAR_POSITIONALog Var søkeord med VAR_KEYWORD.

I tillegg kan du legge til en klausul til om den skulle sjekke om det finnes en standardverdi ved å sjekke om p.defaultlikemenn p.empty.

Svarte 28/07/2017 kl. 12:01
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more