Pasar argumentos de palabras clave a una función cuando los nombres de variables locales son los mismos que los nombres de los parámetros de la función
-
28-10-2019 - |
Pregunta
¿Hay una forma más sucinta de escribir esto?
f(a=a, b=b, c=c, d=d, e=e)
Antecedentes: tengo una función con demasiados argumentos
f(a, b, c, d, e):
pass
En mi programa, tengo variables locales que se denominan exactamente igual que los parámetros de la función.
a, b, c, d, e = range(5)
Me gustaría llamar a la función con argumentos de palabras clave. Dado que las variables se denominan iguales, así es como se vería la llamada.
g = f(a=a, b=b, c=c, d=d, e=e) # this can get very long
Por supuesto, puedo pasar las renovaciones usando la posición en lugar de palabras clave como esta
g = f(a, b, c, d, e)
Pero a
, b
, c
, d
, e
son solo los nombres de las variables en este ejemplo y es fácil ver el orden correcto. Sin embargo, desafortunadamente, las variables en mi programa se nombran más complicadamente y no hay un orden natural fácilmente discernible. Así que realmente me gusta pasarlos por palabra clave para evitar cualquier error.
Solución
Podrías hacer algo como lo siguiente:
a, b, c, d, e = range(5)
arg_dict = lambda l: dict((k, globals()[k]) for k in l.split(', '))
arg_dict('a, b, c, d, e') => {'a': 0, 'c': 2, 'b': 1, 'e': 4, 'd': 3}
, para que pueda llamar a su función así:
f(**arg_dict('a, b, c, d, e'))
Esto le brinda la capacidad de especificar exactamente qué variables desea usar. Un método alternativo para esto que no usa globals()
sería de usar eval()
, pero podría hacer que el Lambda sea potencialmente inseguro.
arg_dict = lambda l: dict(zip(l.split(', '), eval(l)))
Si prefiere pasar locals()
en un argumento en lugar de usar globals()
En la lambda puedes usar lo siguiente:
arg_dict = lambda l, d=locals(): dict((k, d[k]) for k in l.split(', '))
f(**arg_dict('a, b, c, d, e'))
Gracias a sembrado Para el locals()
sugerencias.
Otros consejos
locals()
Da tus variables locales, para que puedas hacer
def somewhere():
x = 3 # its a local
f(**locals()) # same as f(x=3)
Pero seguramente puedes ver cuán frágil es esto.
¿Por qué no puedes usar ** KW aquí?
def foo(**kw):
for k,v in kw.items():
print k,v
foo(a=2)
foo(a=3, b=4)
foo(nonsene=True, blather=False)