domingo, 23 de febrero de 2020

Funciones que imponen nombrar o no parámetros




Cuando se llama a una función Python con parámetros se pueden pasar los valores atendiendo a la posición de los parámetros o referenciando el nombre de los mismos.

A partir de Python 3.8 al declarar una función además puede establecerse qué parámetros, cuando se llame a la función, deben indicarse con su nombre y cuáles no.

Una opción consiste en introducir una barra inclinada hacia la derecha '/' en la definición de la función, entre los parámetros, para obligar a que todos aquellos que se encuentren a su izquierda no puedan referenciar su nombre cuando la función es llamada:

# En este primer ejemplo se muestran los modos habituales
# de llamar a una función (por referencia posicional o por
# nombre): 

def funcion1(x, y, z):
    return x + y + z

print(funcion1(1, 2, 3))  # 6
print(funcion1(x=1, y=2, z=3))  # 6
print(funcion1(z=3, x=1, y=2))  # 6


# En los siguientes casos todos los parámetros a la 
# izquierda de la barra '/' deben indicarse sin nombrar. 
# Si no es así se producirá una excepción de 
# tipo TypeError:

def funcion2(x, y, z, /):
    return x + y + z

print(funcion2(1, 2, 3))  # 6 (es correcta la llamada)
print(funcion2(x=1, y=2, z=3))  # Genera el error siguiente:
# TypeError: funcion2() got some positional-only arguments 
# passed as keyword arguments: 'x, y, z'


def funcion3(x, /, y, z):
    return x + y + z

print(funcion3(x=1, y=2, z=3))  # Genera el error siguiente:
# TypeError: funcion3() got some positional-only arguments 
# passed as keyword arguments: 'x'
# El parámetro 'x' por estar a la izquierda de la barra '/' 
# necesariamente debe indicarse sin nombrar:
print(funcion3(1, z=2, y=3))  # 6

Otra posibilidad es incluir un asterisco '*' entre los parámetros para imponer que todos los que se encuentren a su derecha tengan que referenciar su nombre:

def funcion4(x, y, *, z):
    return x + y + z

print(funcion4(x=1, y=2, z=3))  # 6 (es correcta esta llamada)
print(funcion4(1, 2, 3))  # Genera la siguiente excepción:
# TypeError: funcion4() takes 2 positional arguments 
# but 3 were given
# El parámetro 'z' por estar a la derecha del '*' debe
# ser referenciado con su nombre:
print(funcion4(1, 2, z=3))  # 6

Esta nueva funcionalidad puede resultar de utilidad cuando entre distintas versiones de una API existan funciones que han variado el número de sus parámetros y, por razones de compatibilidad, se prefiera imponer a los desarrolladores el nombrar o no a conveniencia determinados parámetros.



Relacionado: