¿Es ** kwargs un antipatrón?

14

Tenemos una gran cantidad de código en nuestra base de código interna que llama a nuestras bibliotecas internamente. Estas bibliotecas a menudo tienen muchos argumentos (piense en matplotlib) y nuestro código a menudo realiza solo una tarea específica y simplemente pasa el **kwargs a la siguiente función llamada.

Por ejemplo:

def our_method(dataframe, **kwargs):
    result = do_something_with_data(dataframe)
    external_module.draw(result, **kwargs)

Aunque **kwargs nos impide repetir todos los parámetros en nuestra declaración de método, también hace que sea extremadamente opaco qué argumentos son válidos cuando se llama a our_method . Tengo que saber qué método se llama, lo que a menudo no hago. Quiero saber.

¿Cuál es tu opinión sobre esto?

    
pregunta Christian Sauer 22.08.2015 - 09:53

2 respuestas

15

¿Cómo es su código utilizado por los desarrolladores? En otras palabras, ¿qué hacen exactamente para determinar qué argumentos deben usarse y cómo?

  • Si se basan en la documentación generada automáticamente a partir de su código, y el generador no tiene idea de qué hacer con **kwargs , esto es realmente problemático. En lugar de encontrar la lista de argumentos y su significado en la documentación, no tienen absolutamente ninguna información, excepto el vago "se necesitan algunos argumentos".

    Este problema probablemente se pueda resolver documentando el método manualmente, reemplazando la documentación generada automáticamente. Esto requiere un trabajo adicional del implementador del método, pero recuerde que el código (y su documentación) se lee con mucha más frecuencia de lo que está escrito.

  • Si el código es su documentación, los desarrolladores que usan el método con **kwargs necesitan dos pasos adicionales: necesitan no solo mirar la firma del método, sino también su implementación real, para encontrar la otra método que realmente llama. Luego, tienen que recurrir a este otro método para encontrar finalmente lo que estaban buscando.

    Esto no implica mucho esfuerzo, pero aún así, el esfuerzo debe repetirse, una y otra vez. Lo peor es que no puede ayudarlos agregando documentación: si comenta su método, enumera los argumentos reales, existe un gran riesgo de que la próxima versión de la biblioteca a la que llame su método tenga diferentes argumentos, y su documentación estar desactualizado, ya que nadie recordará que debe mantenerse actualizado.

Mi recomendación es confiar en **kwargs solo para los métodos que tienen un alcance reducido. Métodos privados (y por privado en un contexto de Python, me refiero a los métodos que comienzan por _ ) que Se usan en pocos lugares en la clase Son buenos candidatos, por ejemplo. Por otro lado, los métodos que son utilizados por docenas de clases en todo el código base son muy malos candidatos.

Después de todo, no debería tomar demasiado esfuerzo reescribir los argumentos de un método al que llamas dentro del método que escribes. Con suerte, la mayoría de los métodos no toman más de seis a ocho argumentos, y si lo hacen, pregúntese si no debería estar refactorizando el código. En todos los casos:

  • Hacer argumentos explícitos dentro de tu método no requiere mucho esfuerzo,

  • Es posible que luego desees validar los argumentos de todas formas (aunque si solo confías en este punto para que los argumentos sean explícitos, violas YAGNI).

respondido por el Arseni Mourzenko 24.08.2015 - 21:55
3

Si la función del siguiente nivel tiene un __doc__, entonces puedes copiar el __doc__ a tu nueva función.

Por ejemplo:

def a(x):
    """This function takes one parameter, x, and does nothing with it!"""
    pass

def b(**kwargs):
    a(**kwargs)

b.__doc__=a.__doc__

Esto podría aplicarse recursivamente, y podría ser aplicado por un decorador (lo que podría ser útil si lo está haciendo de forma masiva). La cadena __doc__ también podría manipularse para agregar más al final. Esto significa que los parámetros mostrados aún serían kwargs, pero al menos hay documentación en la ayuda que describe los parámetros reales.

    
respondido por el AMADANON Inc. 22.04.2016 - 00:55

Lea otras preguntas en las etiquetas