Contents

Compreender a sobrecarga de funções em Python

A sobrecarga de funções é uma caraterística de algumas linguagens de programação que permite definir variações da mesma função. Cada variante tem o mesmo nome, mas implementações diferentes, com assinaturas de função únicas.

Este método permite a execução de várias acções em função da natureza e da quantidade de parâmetros transmitidos a uma função, permitindo uma maior flexibilidade na programação.

Python difere de linguagens de programação como C\+\+ e Java pelo facto de não suportar inerentemente a sobrecarga de funções. No entanto, é possível emular esta funcionalidade através de meios alternativos.

Como é que Python lida com a sobrecarga de funções?

Em Python, uma função pode ser definida várias vezes com diferentes especificações de parâmetros e/ou tipos de dados. No entanto, ao chamar a função, Python reconhecerá exclusivamente a instância final de sua definição. Apresenta-se de seguida um caso exemplificativo:

 def arithmetics(a, b):
    return a - b

def arithmetics(a, b, c, d):
    return a \\+ b - c * d

print(arithmetics(1, 2, 3, 5)) # returns -12
print(arithmetics(1, 2)) # returns missing positional arguments error

As linguagens de programação orientadas para objectos, como Java, incorporam frequentemente mecanismos de sobrecarga de funções e métodos. Na sua essência, os métodos são funções que são delineadas no contexto de uma classe.

No trecho de código acima mencionado, o interpretador Python reconhecerá exclusivamente a última definição declarada da função arithmetic() ao tentar invocá-la dentro de um projeto. Se se tentar invocar a função com dois parâmetros consistentes com a sua declaração inicial, será levantada uma exceção indicando que esse(s) argumento(s) está(ão) em falta e é(são) necessário(s) para a execução.

/pt/images/missing-positional-argument-error.jpg

A ocorrência de um erro de função não se verifica quando são fornecidos quatro parâmetros durante a invocação, o que indica que a função foi substituída pela sua versão mais recente em memória. No entanto, isto não é indicativo de sobrecarga de métodos e necessita de uma abordagem diferente para a resolução.

Python não suporta inerentemente a sobrecarga de funções; no entanto, é possível empregar certas técnicas no seu código para emular esta funcionalidade.

Método 1: Utilizar parâmetros opcionais ou argumentos predefinidos

É possível efetuar a sobrecarga através da implementação de funções com parâmetros predefinidos. Um exemplo demonstrativo é o seguinte:

 def arithmetics(a, b=0, c=0):
    """
    Arguments:
    a: The first number.
    b: The second number (optional).
    c: The third number (optional).
    """
    return a - b \\+ c

A função dada engloba um total de três variáveis de entrada, mas duas delas possuem valores predefinidos. Consequentemente, isto permite a invocação da função com uma matriz de um a três elementos argumentativos.

 print(arithmetics(1)) # returns 1
print(arithmetics(2, 5)) # returns -3
print(arithmetics(10, 3, 4)) # returns 11

Embora este método apresente vários caminhos para invocar a função, acaba por se revelar uma solução insustentável devido a várias restrições inerentes.

O argumento que é passado tem de ser de um tipo que seja um número inteiro ou um float.

Parece não haver variação discernível na funcionalidade desta função em particular. Consequentemente, continua a ser incapaz de executar tarefas como calcular a área de uma determinada forma ou imprimir o texto “Hello World”.

Método 2: Usando Argumentos Variáveis

Para utilizar a sobrecarga de argumentos variáveis em Python, é essencial incorporar o parâmetro “args” ao definir uma função. Este atributo permite a passagem de vários argumentos posicionais durante a invocação da função. Um exemplo de demonstração pode ser encontrado abaixo:

 def arithmetics(a, *args):
    """
    Arguments:
    a: The first number.
    *args: A variable number of arguments (optional).
    """
    args_sum = 0

    for num in args:
        args_sum *= num

    return a - args_sum

print(arithmetics(1)) # returns 1
print(arithmetics(2, 5)) # returns 2
print(arithmetics(10, 3, 4, 2, 4, 6)) # returns 10

A função acima mencionada requer dois parâmetros; um parâmetro obrigatório designado por “a” e um parâmetro opcional referido como “args”, permitindo a inclusão de qualquer número de argumentos adicionais, conforme necessário.

Apesar da sua capacidade de aceitar numerosos inputs, esta função em particular está limitada na sua capacidade de efetuar operações aritméticas para além da simples multiplicação, pois aplica exclusivamente o processo de multiplicação às variáveis representadas pela palavra-chave args .

Para executar uma série de acções num contexto programático, é muitas vezes necessário incorporar declarações condicionais no código. No entanto, à medida que o número de condições a considerar aumenta, também aumenta a complexidade da tarefa de programação em causa.

Método 3: Usando o Decorador de Despacho Múltiplo

O Decorador de Despacho Múltiplo é uma biblioteca Python que permite a criação de várias implementações ou instâncias de uma única função, dependendo do tipo de entrada que ela recebe. Ao fazê-lo, é possível estabelecer funções idênticas com estruturas de dados diferentes e alterar totalmente a sua conduta.

Para utilizar o adorno de envio de vários métodos, siga estes protocolos:

⭐ Instale o multipledispath no seu ambiente Python:

 pip install multipledispatch

⭐ Decore sua(s) função(ões) com o decorador @dispatch. O decorador @dispatch é um decorador Python que permite que você implemente múltiplos despachos. Ele despachará automaticamente a função apropriada com base nos argumentos que você passar para ele. Pode utilizar o decorador @dispatch seguindo este padrão:

 from multipledispatch import dispatch

@dispatch(data type1, data type2, data typeX)
def your_function(a, b, c, x):
    pass
    # perform your operations here

Considere um cenário em que empregamos a utilização do decorador de envio múltiplo para facilitar o conceito de sobrecarga de funções na linguagem de programação Python:

 from multipledispatch import dispatch

@dispatch(int, int)
def add(a, b):
    """
    Arguments:
    a: Any integer.
    b: Any integer.
    """
    return a \\+ b

@dispatch(int, list)
def add(a, b):
    """
    Arguments:
    a: Any integer.
    b: Any Python list.
    """
    b.append(a)
    return b

# returns 3
print(add(1, 2))

# returns [2, 3, 4, 5, 'w', 'done', 1]
print(add(1, [2, 3, 4, 5, 'w', 'done'])) 

O segmento de código acima mencionado instancia duas ocorrências separadas da função add(), com cada ocorrência respectiva aceitando e processando parâmetros distintos. Especificamente, uma dessas ocorrências recebe e calcula o agregado de dois valores numéricos representados como tipos de dados inteiros, produzindo em última análise o total resultante em termos do resultado de uma operação aritmética.

De forma alternada, a iteração subsequente desta operação envolve a aceitação de dois parâmetros: um número inteiro e uma coleção sequencial. Subsequentemente, o referido parâmetro é adicionado ao final da série e devolvido como a acumulação alterada.

/pt/images/using-the-dispatch-decorator-for-method-overloading.jpg

Esta abordagem à sobrecarga de funções em Python dá-lhe muita flexibilidade, especialmente se precisar de alterar o comportamento do seu método. Pode saber mais na documentação sobre o despacho múltiplo .

A Melhor Abordagem para a Sobrecarga de Funções em Python

A seleção de uma metodologia apropriada para a sobrecarga funcional deve estar alinhada com os objectivos pretendidos. Nos casos em que o resultado desejado pode ser alcançado através da utilização de argumentos padrão ou variáveis, pode não ser necessário empregar o decorador multi-dispatch. No entanto, na maioria dos casos, este último apresenta-se como uma solução mais eficiente e precisa devido à sua capacidade de acomodar vários tipos de argumentos, mantendo um desempenho ótimo.

O decorador fornecido oferece uma abordagem elegante e versátil para implementar a sobrecarga de funções na linguagem de programação Python. Permite a criação de várias implementações de uma única função, dependendo das características dos seus parâmetros.

A utilização deste método permite o desenvolvimento de funções versáteis capazes de acomodar uma variedade de tipos de parâmetros, eliminando a necessidade de declarações condicionais complexas para alcançar tal adaptabilidade.