He estado buscando el código fuente de un paquete de código abierto que estoy usando. Casi todas las funciones usan * argumentos en lugar de argumentos con nombre. Me resulta difícil seguir y utilizar el código, porque cada vez que quiero llamar a una función, tengo que volver atrás, seleccionar el código fuente e identificar cuáles deberían ser los argumentos y en qué orden deberían estar. La pregunta que tengo es esta: ¿hay alguna razón convincente para usar * args en cada función, o es esto un abuso del concepto? Gracias , -bUso adecuado frente al uso excesivo de * args en Python
Respuesta
Esto podría ser un razonamiento personal, pero solo uso * args y ** kwargs cuando tengo muchos campos opcionales donde algunos campos solo se usan en un contexto determinado.
La única otra ocasión que utilicé args es cuando estaba construyendo un cliente XML RPC para una API en la nube. Como solo estaba pasando los parámetros a una capa subyacente y como la función se generó dinámicamente, no tuve más remedio que usar * args ya que no tenía manera de conocer todos los parámetros de antemano.
En la mayoría de los casos, ni siquiera lo necesitará. Considero que es mayormente pereza que cualquier otra cosa.
Algunas personas que provienen de Java y C# pueden usar esto como reemplazo de "params", pero hay tantas formas de pasar parámetros opcionales en python.
Y acepto que incluso si usa * args, debe tener una muy buena documentación.
En dos años de codificación C# He usado 'params' dos veces. En un mes de Python, he visto '(* args, ** kwargs)' tantas veces que me sangran los ojos. Recomendaría usarlo con moderación; es una herramienta que debería usarse para resolver un problema muy específico. Y como sabemos, cuando le das a las personas una herramienta que es así de fácil de usar, abusarán de ella y abusarán de ella sin fin. – Dagrooms
Uso *args
en cada función es una mala idea, ya que puede enmascarar errores en su código (llamar a una función con un número incorrecto de argumentos). Supongo que la regla de oro debería ser usar *args
solo si necesita*args
.
Cuando no hay una razón de peso para usar *args
, es un abuso del concepto. Por lo general, hay buenos nombres para los argumentos, que ayudan a la comprensión. Incluso cuando no los hay, (x, y, z)
le dice más de (*args)
.
Y más allá de hacer el código más legible, sino que también ayuda a detectar errores (por ejemplo, si se llama a una función (x, y, z)
con (2, 3)
obtendrá un error en la llamada, en lugar de en el interior de la función), por lo general es más concisa , e incluso puede ser más eficiente.
Pero a veces hay razones apremiantes para el uso generalizado de *args
.
Por ejemplo, si está envolviendo un módulo de nivel inferior (C o de otro modo) y desea un reenvío perfecto, es más fácil con *args
. Aún más si está generando automáticamente el código del contenedor en lugar de escribirlo manualmente. Por supuesto, esto sigue siendo una solución de compromiso, es mucho más fácil para el desarrollador del módulo envoltorio, pero más difícil para los usuarios, pero a veces vale la pena el intercambio.
Sin conocer el paquete específico al que se refiere, es imposible adivinar si se trata de un caso de uso convincente o un abuso.
En el Zen of Python, se nos dice que preferimos explícitamente más que implícita. Los argumentos explícitos deben usarse siempre que sea posible.
+1, citando del Zen. – nneonneo
@nneonneo Citar del Zen sin más comentarios es bastante inútil. Las pautas en el Zen de Python son geniales, pero no solo porque están en el Zen de Python, son buenas ideas para * buenas razones *. Memorizar el Zen de Python sin * entender * los motivos de esas pautas (para que pueda reconocer al partir de ellas) no lo ayuda a aplicarlas bien. – Ben
@Ben, no pensé que era mi lugar para especular sobre por qué ese artículo en particular está en el Zen. En este caso, pensé que era bastante obvio: explícito es más fácil de entender y seguir. También descubrí que trabajar con los mismos principios que guían a tu diseñador de plataforma simplemente mejora las cosas en general, no solo en Python. –
Si está ajustando una función desconocida (las funciones devueltas por los decoradores suelen hacerlo), a menudo necesita utilizar (*args, **kwargs)
.
Algunas jerarquías de clases usan (*args, **kwargs)
en métodos que pueden necesitar diferentes firmas en diferentes clases en las jerarquías (__init__
es uno de los principales culpables). Es realmente útil si puede evitar eso, pero puede ser necesario trabajar con múltiples jerarquías de herencia de una manera sensata (o tan cuerdo como sea posible con herencia múltiple, al menos).
A veces termino usando **kwargs
cuando tengo una gran cantidad de argumentos opcionales, pero esto requiere mucha documentación.
En una función que está consumiendo el *args
en sí (en lugar de pasarlos a alguna otra función con una firma desconocida, como en los casos de decorador o herencia de clases), a continuación, tiendo a pensar que *args
casi nunca deben usarse con excepción de significa "cero o más del mismo tipo de cosas". Y en ese caso debería nombrarlo *websites
o *spaceships
o *watermelons
, no *args
. Un grupo de parámetros no relacionados no debe aplastarse en *args
. Lo peor sería que la función use *args
para tomar "an x, a y, z, o bien una x y una z", donde el segundo parámetro hace cosas diferentes dependiendo de cuántos parámetros se pasan. En ese punto, todos deberían tener nombres y valores predeterminados (incluso si es solo el estándar None
predeterminado, luego ver en la función cuáles no son None
patrón) y se pasan por palabra clave en lugar de por posición.
- 1. Uso adecuado de mutexes en Python
- 2. Uso excesivo deIntegral en Haskell
- 3. El uso excesivo de jQuery
- 4. El uso excesivo de `this` en C++
- 5. Uso adecuado de RuntimeException?
- 6. C++ - ¿Uso excesivo de métodos virtuales?
- 7. ¿El uso excesivo de DataTable es malo?
- 8. Plano de matraces uso adecuado
- 9. Etiquetas HTML 'contenedor': uso adecuado?
- 10. Uso adecuado del atributo [Importar] en MEF
- 11. ¿Cómo evitar el uso excesivo de patrones de diseño?
- 12. ¿Cómo uso getConstructor (params) .newInstance (args)?
- 13. ¿Es este un uso excesivo de la abstracción?
- 14. Uso adecuado de JTidy para purificar HTML
- 15. El uso adecuado de intentar coger ..
- 16. Uso excesivo de ASP.Net de los controles de usuario
- 17. Consejos para evitar el uso excesivo de métodos estáticos
- 18. Uso adecuado de yieldIfContendedSafely() en una aplicación multiproceso de Android
- 19. rails + brújula: ventajas frente al uso de haml + blueprint directamente
- 20. El uso adecuado de KeepAlive en Apache .htaccess
- 21. Uso adecuado de pila y pila en C++?
- 22. Uso ordenados() en Python
- 23. Caché de AppFabric: uso adecuado de DataCacheFactory y DataCache
- 24. Uso de eval en Python?
- 25. Uso de pickle.dump en Python
- 26. Uso de RSA en Python
- 27. ListView frente a ListBox para uso de columna múltiple
- 28. ¿Cómo pasar args al método en java, como f (* args) en python?
- 29. ¿Es este un uso adecuado de una std :: string temporal?
- 30. C# utilizando la palabra clave, el uso adecuado de él
Si hay * args, tiene que haber un docstring (¡exacto!). – James
¿Qué paquete es? No jugar el juego de la culpa, pero pueden tener una razón válida. –