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

StackOverflow https://stackoverflow.com/questions/5860974

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.

¿Fue útil?

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)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top