Sé que no es pitónico escribir funciones que se preocupen por el tipo de argumentos, pero hay casos en los que es simplemente imposible ignorar tipos porque se manejan de manera diferente.Decorador para sobrecargar en Python
Tener un montón de isinstance
comprobaciones en su función es feo; ¿Hay algún decorador de funciones disponible que habilite las sobrecargas de funciones? Algo como esto:
@overload(str)
def func(val):
print('This is a string')
@overload(int)
def func(val):
print('This is an int')
Actualización:
Aquí hay algunos comentarios que dejé en David Zaslavsky's answer:
Con unas pocas modificaciones [s], esto va a satisfacer mis propósitos bastante bien. Otra limitación que noté en su implementación, ya que usa
func.__name__
como la clave del diccionario, es propenso a nombrar colisiones entre módulos, lo que no siempre es deseable. [Continuación][cont.] Por ejemplo, si tengo un módulo que sobrecarga
func
, y otro módulo completamente ajenos que también sobrecargafunc
, estas sobrecargas chocarán porque el dict función de despacho es global. Ese dict debería hacerse local al módulo, de alguna manera. Y no solo eso, también debería apoyar algún tipo de 'herencia'. [continuación][cont.] Por 'herencia' me refiero a esto: digamos que tengo un módulo
first
con algunas sobrecargas. Luego dos módulos más que no están relacionados pero cada uno importafirst
; ambos módulos agregan nuevas sobrecargas a las ya existentes que acaban de importar. Estos dos módulos deberían poder usar las sobrecargas enfirst
, pero los nuevos que acaban de agregar no deberían colisionar entre ellos entre los módulos. (Esto es realmente muy difícil hacerlo bien, ahora que lo pienso.)
Algunos de estos problemas podrían resolverse posiblemente cambiando la sintaxis de decorador un poco:
first.py
@overload(str, str)
def concatenate(a, b):
return a + b
@concatenate.overload(int, int)
def concatenate(a, b):
return str(a) + str(b)
second.py
from first import concatenate
@concatenate.overload(float, str)
def concatenate(a, b):
return str(a) + b
Hmm ... así que en su edición, ¿qué quiere decir con 'contatenate.overload' en' first.py'? Como está escrito, esto intentaría acceder al atributo 'sobrecarga' de la función' concatenar', que no existe en este ejemplo. –
@DavidZaslavsky La primera sobrecarga de la función debe decorarse con '@ overload', que devolverá un objeto invocable que tenga y atribuirá' overload'. Todas las sobrecargas posteriores deberían decorarse con este objeto ya existente, '@ object.overload', por lo que solo hay una dict por objeto, no una dict global. (Funciona de manera similar a la 'propiedad @ estándar.) Escribiré una implementación y le notificaré cuando la publique. –
Eso sería una desviación de la sintaxis de sobrecarga tradicional. Pero si eso es lo que quieres, echa un vistazo al [paquete de sobrecarga] (http://pypi.python.org/pypi/overload/1.1) (que estoy a punto de editar en mi respuesta). Utiliza esencialmente ese método. –