Estoy tratando de generar un dictado que contenga los nombres y el valor de la llamada actual de parámetros que no son None . Esto se siente como algo que debería estar integrado, pero no puedo encontrar nada que lo haga en la documentación de Python.
por ejemplo, cuando
def foo(limit=None, offset=None, lower_bound=None, upper_bound=None): # code to generate dict of non-`None` named arguments (see below) ... # other things happen later se llama con los parámetros foo(limit=5, lower_bound=100) , necesito el siguiente dict: {limit=5, lower_bound=100} .
¿Hay algo que convenientemente hace eso por mí?
Hasta ahora, he investigado lo siguiente, todos los cuales parecen defectuosos:
def foo(limit=None, offset=None, lower_bound=None, upper_bound=None): keys = ('limit', 'offset', 'lower_bound', 'upper_bound') values = (limit, offset, lower_bound, upper_bound) magic_dict = {k: v for k, v in zip(keys, values) if v is not None}locals() — enlace — que necesitaría eliminar todo lo que no debería estar en el diccionario (es decir, las claves con el valor de None ). Esto también parece potencialmente propenso a errores si las definiciones de variables se agregan sobre el código del diccionario mágico , que también debería eliminarse. def foo(limit=None, offset=None, lower_bound=None, upper_bound=None): magic_dict = {k: v for k, v in locals().items() if v is not None}inspect 's - link - signature y bind , que aún requiere una lista de los parámetros def foo(limit=None, offset=None, lower_bound=None, upper_bound=None): sig = signature(foo) sig_args = sig.bind(limit, offset, lower_bound, upper_bound).arguments magic_dict = {k: v for k, v in sig_args.items() if v is not None} Otros pensamientos incluyeron hacer una clase para que getattr esté disponible
Parece que me estoy perdiendo algo obvio: ¡se agradecerán los comentarios!
Alguien sugirió ¿Cuál es una forma elegante de seleccionar todos los elementos que no son Ninguno de los parámetros y colocarlos en un diccionario de Python? , cuyas respuestas son principalmente "mover a **kwargs ". Mi reacción inicial es que preferiría mantener una lista específica de argumentos: ¿es mala lógica para mí? ¿Cuál es la mejor práctica típica con Python?
Puedes intentar usar decoradores:
def capture(func): capture.kwds = None def wrap(*args, **kwargs): capture.kwds = kwargs return func(*args, **kwargs) return wrap @capture def foo(limit=None, offset=None, lower_bound=None, upper_bound=None): return NoneAhora puedes llamar:
>>> foo(limit=1, offset=2, lower_bound=3, upper_bound=4) None >>> capture.kwds {'limit': 1, 'offset': 2, 'lower_bound': 3, 'upper_bound': 4}También puede usar el método local, pero copie los locales en la parte superior de su función. Al final, uno puede usar las claves de los locales originales y seleccionar solo aquellos en la declaración de devolución:
def foo(a=None, b=None, c=None): original_locals = locals().copy() d = 'test' #Test adding new variable which should not be returned return {k:v for k,v in locals().items() if k in original_locals.keys() and v is not None} foo(1) >> {'a': 1} foo(1, 2, 3) >> {'a': 11, 'b': 2, 'c': 3}Tenga en cuenta que debe copiar los locales, de lo contrario, este método no funcionará.
Si también desea agregar kwargs :
def func(a=None, b=None, c=None, **kwargs): org_loc = locals().copy() def check_kwargs(d): if 'kwargs' in d.keys(): d.update(d['kwargs']) del d['kwargs'] check_kwargs(org_loc) d = 'test' new_loc = locals() check_kwargs(new_loc) return {k:v for k,v in new_loc.items() if k in org_loc.keys() and v is not None}Luego:
func(1) >> {'a':1} func(1, test='test') >> {'a': 1, 'test': 'test'}