coding-style - sirven - palabras claves ejemplos
¿Alguna razón para NO usar siempre argumentos de palabra clave? (11)
Antes de saltar a Python, comencé con algunos libros de Objective-C / Cocoa. Según recuerdo, la mayoría de las funciones requerían argumentos de palabra clave para ser explícitamente establecidos. Hasta hace poco, olvidé todo sobre esto, y solo usé argumentos posicionales en Python. Pero últimamente, me encontré con algunos errores que resultaron de posiciones incorrectas, pequeñas cosas furtivas que eran.
Me hizo pensar, en términos generales, a menos que exista una circunstancia que requiera específicamente argumentos que no sean palabras clave, ¿hay alguna buena razón para NO usar argumentos de palabras clave? ¿Se considera un mal estilo usarlos siempre, incluso para funciones simples?
Siento que como la mayoría de mis programas de 50 líneas han escalado a 500 o más líneas regularmente, si me acostumbro a usar siempre argumentos de palabras clave, el código será más fácil de leer y mantener a medida que vaya creciendo. ¿Alguna razón por la que esto podría no ser así?
ACTUALIZAR:
La impresión general que estoy obteniendo es que es una preferencia de estilo, con muchos buenos argumentos de que, por lo general, no se deben usar para argumentos muy simples, pero que por lo demás son consistentes con un buen estilo. Antes de aceptar, solo quiero aclararlo: ¿hay algún problema específico que no sea de estilo que surja de este método? Por ejemplo, ¿éxitos de rendimiento significativos?
A veces, las cosas deberían ser simples porque son simples.
Si siempre lo obliga a usar argumentos de palabra clave en cada llamada a función, pronto su código será ilegible.
Bueno, hay algunas razones por las que no haría eso.
Si todos sus argumentos son argumentos de palabra clave, aumenta el ruido en el código y puede eliminar la claridad sobre qué argumentos son necesarios y cuáles son opcionales.
Además, si tengo que usar tu código, ¡quizás quiera matarte! (Es una broma), pero tener que escribir el nombre de todos los parámetros cada vez ... no es tan divertido.
Cuando las funciones incorporadas de compile()
y __import__()
ganan soporte para los argumentos de palabras clave , el mismo argumento se hizo a favor de la claridad. Parece que no hay un rendimiento significativo, si corresponde.
Ahora, si hace que sus funciones solo acepten argumentos de palabra clave (en lugar de pasar los parámetros posicionales usando palabras clave cuando los llama, lo cual está permitido), entonces sí, sería molesto.
Los argumentos de las palabras clave son buenos cuando tienes largas listas de parámetros sin un orden bien definido (que no se te ocurre fácilmente un esquema claro para recordar); Sin embargo, hay muchas situaciones en las que su uso es excesivo o hace que el programa sea menos claro.
En primer lugar, a veces es mucho más fácil recordar el orden de las palabras clave que los nombres de los argumentos de palabras clave, y especificar los nombres de los argumentos podría hacerlo menos claro. Tome randint
de scipy.random
con la siguiente docstring:
randint(low, high=None, size=None)
Return random integers x such that low <= x < high.
If high is None, then 0 <= x < low.
Cuando quiero generar un int aleatorio a partir de [0,10) es más claro escribir randint(10)
que randint(low=10)
en mi opinión. Si necesita generar una matriz con 100 números en [0,10) probablemente pueda recordar el orden de los argumentos y escribir randint(0, 10, 100)
. Sin embargo, es posible que no recuerde los nombres de las variables (por ejemplo, es el primer parámetro bajo, inferior, inicio, mínimo, mínimo) y una vez que tenga que buscar los nombres de los parámetros, es mejor que no los use (ya que acaba de buscarlos) el orden correcto).
También considere las funciones variadas (las que tienen un número variable de parámetros anónimos). Por ejemplo, es posible que desee escribir algo como:
def square_sum(*params):
sq_sum = 0
for p in params:
sq_sum += p*p
return sq_sum
que se puede aplicar un conjunto de parámetros simples ( square_sum(1,2,3,4,5) # gives 55
). Claro que podrías haber escrito la función para tomar una palabra clave con nombre def square_sum(params):
y la llamé como square_sum([1,2,3,4,5])
pero eso puede ser menos intuitivo, especialmente cuando no hay confusión potencial sobre el nombre del argumento o su contenido.
No hay ninguna razón para no utilizar argumentos de palabras clave aparte de la claridad y la legibilidad del código. La opción de usar palabras clave debe basarse en si la palabra clave agrega información útil adicional al leer el código o no.
Sigo la siguiente regla general:
- Si es difícil inferir la función (nombre) del argumento a partir del nombre de la función, páselo por palabra clave (por ejemplo, no me gustaría tener
text.splitlines(True)
en mi código). - Si es difícil inferir el orden de los argumentos, por ejemplo, si tiene demasiados argumentos, o si tiene argumentos opcionales independientes, páselo por palabra clave (por ejemplo,
funkyplot(x, y, None, None, None, None, None, None, ''red'')
no se ve particularmente bien). - Nunca pase los primeros argumentos por palabra clave si el propósito del argumento es obvio. Verán,
sin(2*pi)
es mejor quesin(value=2*pi)
, lo mismo es cierto para laplot(x, y, z)
.
En la mayoría de los casos, los argumentos obligatorios estables serían posicionales, y los argumentos opcionales serían palabras clave.
También hay una posible diferencia en el rendimiento, porque en cada implementación los argumentos de la palabra clave serían un poco más lentos, pero teniendo en cuenta que esto sería generalmente una optimización prematura y los resultados no serían significativos, no creo que sea crucial para la decisión .
ACTUALIZACIÓN: preocupaciones no estilísticas
Los argumentos de las palabras clave pueden hacer todo lo que los argumentos de posición pueden, y si está definiendo una nueva API, no hay desventajas técnicas aparte de posibles problemas de rendimiento. Sin embargo, puede tener pequeños problemas si combina su código con elementos existentes.
Considera lo siguiente:
- Si haces que tu función tome argumentos de palabra clave, eso se convierte en parte de tu interfaz. No puede reemplazar su función por otra que tenga una firma similar, sino una palabra clave diferente para el mismo argumento.
- Es posible que desee utilizar un decorador u otra utilidad en su función que asume que su función toma un argumento posicional. Los métodos sin consolidar son un ejemplo de dicha utilidad porque siempre pasan el primer argumento como posicional después de leerlo como posicional, por lo que
cls.method(self=cls_instance)
no funciona incluso si hay un argumentoself
en la definición.
Ninguno de estos sería un problema real si diseña bien su API y documenta el uso de argumentos de palabra clave, especialmente si no está diseñando algo que debería ser intercambiable con algo que ya existe.
No veo el propósito de usar argumentos de palabras clave cuando el significado de los argumentos es obvio
Recuerdo haber leído una muy buena explicación de "opciones" en los programas de UNIX: "Las opciones deben ser opcionales, un programa debería poder ejecutarse sin ninguna opción".
El mismo principio podría aplicarse a los argumentos de palabra clave en Python. Este tipo de argumentos debería permitir a un usuario "personalizar" la llamada a la función, pero una función debería poder invocarse sin ningún tipo de argumento de argumento de valor de palabra implícito.
Si su consideración es mejorar la legibilidad de las llamadas a funciones, ¿por qué no simplemente declarar las funciones como normales, por ejemplo?
def test(x, y):
print "x:", x
print "y:", y
Y simplemente llame a las funciones declarando explícitamente los nombres, como sigue:
test(y=4, x=1)
Lo que obviamente le da la salida:
x: 1
y: 4
o este ejercicio sería inútil.
Esto evita que los argumentos sean opcionales y necesiten valores predeterminados (a menos que desee que sean, en cuyo caso simplemente continúe con los argumentos de palabra clave! :) y le ofrece toda la versatilidad y legibilidad mejorada de los argumentos nombrados que no están limitados por orden.
Solo para ofrecer un argumento diferente, creo que hay algunos casos en los que los parámetros nombrados podrían mejorar la legibilidad. Por ejemplo, imagine una función que crea un usuario en su sistema:
create_user("George", "Martin", "[email protected]", "[email protected]", "1", "Radius Circle")
A partir de esa definición, no está del todo claro lo que estos valores podrían significar, a pesar de que son todos necesarios, sin embargo, con parámetros con nombre siempre es obvio:
create_user(
first_name="George",
last_name="Martin",
contact_email="[email protected]",
billing_email="[email protected]",
street_number="1",
street_name="Radius Circle")
Un error que hago a menudo es que olvidé que los argumentos posicionales deben especificarse antes de cualquier argumento de palabra clave cuando se llama a una función. Si la testing
es una función, entonces:
testing(arg = 20, 56)
da un mensaje SyntaxError
; algo como:
SyntaxError: non-keyword arg after keyword arg
Es fácil de arreglar, por supuesto, es simplemente molesto. Entonces, en el caso de programas de pocas líneas como los que mencionas, probablemente iría con argumentos posicionales después de dar nombres agradables y descriptivos a los parámetros de la función. No sé si lo que mencioné es un gran problema.
Una desventaja que pude ver es que tendría que pensar en un valor predeterminado sensato para todo y, en muchos casos, podría no haber ningún valor predeterminado razonable (incluido None
). Entonces se sentiría obligado a escribir un montón de código de manejo de errores para los casos en que un kwarg que lógicamente debería ser un argumento posicional no se especificara.
Imagina escribir cosas como esta cada vez ...
def logarithm(x=None):
if x is None:
raise TypeError("You can''t do log(None), sorry!")