¿Cuál es la forma correcta de usar **kwargs
en Python cuando se trata de valores predeterminados?
kwargs
devuelve un diccionario, pero ¿cuál es la mejor manera de establecer valores predeterminados, o hay alguno? ¿Debo acceder a él como un diccionario? Utilice la función get?
class ExampleClass:
def __init__(self, **kwargs):
self.val = kwargs['val']
self.val2 = kwargs.get('val2')
Una pregunta simple, pero en la que no puedo encontrar buenos recursos. La gente lo hace de diferentes maneras en el código que he visto y es difícil saber qué usar.
__init__()
. ¿Alguien puede explicar por qué esta es una transgresión digna de pelusa?self.__dict__update(**kwargs)
puede redefinir métodos y causar otros erroresSi bien la mayoría de las respuestas dicen eso, por ejemplo,
es lo mismo que"
esto no es verdad. En este último caso,
f
puede ser llamado comof(23, 42)
, mientras que el primer caso acepta argumentos con nombre sólo - no hay llamadas posicionales. A menudo, desea permitir que la persona que llama tenga la máxima flexibilidad y, por lo tanto, es preferible la segunda forma, como afirman la mayoría de las respuestas: pero ese no es siempre el caso. Cuando acepta muchos parámetros opcionales, de los cuales generalmente solo se pasan unos pocos, puede ser una excelente idea (¡evitar accidentes y códigos ilegibles en sus sitios de llamadas!) Forzar el uso de argumentos con nombre,threading.Thread
es un ejemplo. La primera forma es cómo implementar eso en Python 2.El idioma es tan importante que en Python 3 ahora tiene una sintaxis de soporte especial: cada argumento después de un solo
*
en ladef
firma es solo de palabra clave, es decir, no se puede pasar como un argumento posicional, sino solo como uno con nombre. Entonces, en Python 3 podría codificar lo anterior como:De hecho, en Python 3 incluso puede tener argumentos de solo palabras clave que no son opcionales (los que no tienen un valor predeterminado).
Sin embargo, Python 2 todavía tiene largos años de vida productiva por delante, por lo que es mejor no olvidar las técnicas y expresiones idiomáticas que le permiten implementar en Python 2 ideas de diseño importantes que se admiten directamente en el lenguaje de Python 3.
fuente
Sugiero algo como esto
Y luego usa los valores como quieras
dictionaryA.update(dictionaryB)
agrega el contenido dedictionaryB
adictionaryA
sobrescribir los duplicados de las llaves.fuente
for key in options: self.__setattr__(key, options[key])
y estoy listo para ir. :)Tu harias
o
Si lo usa
pop
, puede verificar si hay valores falsos enviados y tomar las medidas apropiadas (si corresponde).fuente
.pop
lo ayudaría a "verificar si hay valores falsos enviados"?kwargs
por una razón.default_value
pasada? ¿Y quita esa llave después?Usar ** kwargs y valores predeterminados es fácil. A veces, sin embargo, no deberías usar ** kwargs en primer lugar.
En este caso, realmente no estamos haciendo el mejor uso de ** kwargs.
Lo anterior es un "¿por qué molestarse?" declaración. Es lo mismo que
Cuando usa ** kwargs, quiere decir que una palabra clave no es solo opcional, sino condicional. Hay reglas más complejas que los valores predeterminados simples.
Cuando usa ** kwargs, generalmente quiere decir algo más parecido a lo siguiente, donde los valores predeterminados simples no se aplican.
fuente
Como
**kwargs
se usa cuando se desconoce el número de argumentos, ¿por qué no hacer esto?fuente
Aquí hay otro enfoque:
fuente
get_form_kwargs()
). ccbv.co.uk/projects/Django/1.5/django.views.generic.edit/…get_form()
método muestra cómo obtener argumentos de palabras clave ampliamente difiriendo a otro método (get_form_kwargs
como se mencionó anteriormente). Se crea una instancia del formulario como sigue:form_class(**self.get_form_kwargs())
.get_form_kwargs()
en una vista de subclase y agregar / eliminar kwargs según una lógica específica. Pero eso es para un tutorial de Django.Creo que la forma correcta de usar
**kwargs
en Python cuando se trata de valores predeterminados es usar el método de diccionariosetdefault
, como se indica a continuación:De esta manera, si un usuario pasa 'val' o 'val2' en la palabra clave
args
, se usarán; de lo contrario, se usarán los valores predeterminados que se hayan establecido.fuente
Podrías hacer algo como esto
fuente
El seguimiento de @srhegde sugerencia de utilizar setattr :
Esta variante es útil cuando se espera que la clase tenga todos los elementos de nuestra
acceptable
lista.fuente
Si desea combinar esto con * args, debe mantener * args y ** kwargs al final de la definición.
Entonces:
fuente
@AbhinavGupta y @Steef sugirieron usar
update()
, lo que me pareció muy útil para procesar grandes listas de argumentos:¿Qué sucede si queremos verificar que el usuario no haya pasado ningún argumento falso / no admitido? @VinaySajip señaló que
pop()
se puede usar para procesar iterativamente la lista de argumentos. Entonces, cualquier argumento sobrante es falso. Agradable.Aquí hay otra forma posible de hacer esto, que mantiene la sintaxis simple de uso
update()
:unknown_args
es un queset
contiene los nombres de los argumentos que no aparecen en los valores predeterminados.fuente
Otra solución simple para procesar argumentos desconocidos o múltiples puede ser:
fuente
** kwargs le da la libertad de agregar cualquier número de argumentos de palabras clave. Uno puede tener una lista de claves para las cuales puede establecer valores predeterminados. Pero establecer valores predeterminados para un número indefinido de teclas parece innecesario. Finalmente, puede ser importante tener las claves como atributos de instancia. Entonces, haría esto de la siguiente manera:
fuente