documentação - Como uso a sobrecarga de métodos no Python?



django python 3 pdf (10)

Eu estou tentando implementar sobrecarga de método no Python:

class A:
    def stackoverflow(self):    
        print 'first method'
    def stackoverflow(self, i):
        print 'second method', i

ob=A()
ob.stackoverflow(2)

mas a saída é o second method 2 ; similarmente:

class A:
    def stackoverflow(self):    
        print 'first method'
    def stackoverflow(self, i):
        print 'second method', i

ob=A()
ob.stackoverflow()

Traceback (most recent call last):
  File "my.py", line 9, in <module>
    ob.stackoverflow()
TypeError: stackoverflow() takes exactly 2 arguments (1 given)

Como faço isso funcionar?

https://ffff65535.com


A sobrecarga de método não substitui o método. E em Python, você faz tudo em uma função:

class A:

    def (self, i='some_default_value'):    
        print 'only method'

ob=A()
ob.(2)
ob.()

Você não pode ter dois métodos com o mesmo nome no Python - e você não precisa.

Veja a seção Default Argument Values do tutorial do Python. Veja "Menor Admiração" e o Argumento de Mutação Padrão para um erro comum a ser evitado.

Edit : Veja PEP 443 para obter informações sobre as novas funções genéricas de despacho único no Python 3.4.


Acabou de encontrar este github.com/bintoro/overloading.py para qualquer pessoa que possa estar interessada.

Do readme do repositório vinculado:

A sobrecarga é um módulo que fornece o despacho de funções com base nos tipos e no número de argumentos de tempo de execução.

Quando uma função sobrecarregada é chamada, o dispatcher compara os argumentos fornecidos com as assinaturas de função disponíveis e chama a implementação que fornece a correspondência mais precisa.

Características

A validação de funções no registro e regras detalhadas de resolução garantem um resultado único e bem definido em tempo de execução. Implementa o cache de resolução de função para um ótimo desempenho. Suporta parâmetros opcionais (valores padrão) em assinaturas de função. Avalia argumentos posicionais e de palavra-chave ao resolver a melhor correspondência. Suporta funções de fallback e execução de código compartilhado. Suporta polimorfismo de argumento. Suporta classes e herança, incluindo classmethods e staticmethods.


Enquanto a @agf estava certa com a resposta no passado, agora com o PEP-3124 nós temos nossa sintaxe mais sugestiva. Consulte a @overload sobre o @overload decorator, mas observe que isso é apenas uma sugestão de sintaxe e IMHO, isso é o que as pessoas vêm discutindo desde então. Pessoalmente eu concordo que ter múltiplas funções com assinaturas diferentes torna mais legível, em seguida, ter uma única função com mais de 20 argumentos definidos para um valor padrão ( None maior parte do tempo) e depois ter que mexer em cadeias if , elif , else para descobrir o que o chamador realmente deseja que nossa função faça com o conjunto de argumentos fornecido. Isso, isso é muito atrasado após o Python Zen

Linda é melhor que feia.

e sem dúvida também

Simples é melhor que complexo.

Diretamente da documentação oficial do Python vinculada acima:

@overload
def process(response: None) -> None:
    ...
@overload
def process(response: int) -> Tuple[int, str]:
    ...
@overload
def process(response: bytes) -> str:
    ...
def process(response):
    <actual implementation>

Eu acho que a palavra que você está procurando é "sobrecarregar". Não há sobrecarga de método em python. Você pode, no entanto, usar argumentos padrão, como segue.

def (self, i=None):
    if i != None:     
        print 'second method', i
    else:
        print 'first method'

Quando você passar um argumento, ele seguirá a lógica da primeira condição e executará a primeira instrução de impressão. Quando você não passar nenhum argumento, ele irá para a condição else e executará a segunda instrução de impressão.


Eu escrevo minha resposta no Python 3.2.1.

def overload(*functions):
    return lambda *args, **kwargs: functions[len(args)](*args, **kwargs)

Como funciona:

  1. overload pega qualquer quantia de callables e armazena-os em functions tuple, então retorna lambda.
  2. O lambda pega qualquer quantidade de argumentos, então retorna o resultado da função de chamada armazenada em functions[number_of_unnamed_args_passed] chamadas com argumentos passados ​​para o lambda.

Uso:

class A:
    =overload(                    \
        None, \ 
        #there is always a self argument, so this should never get called
        lambda self: print('First method'),      \
        lambda self, i: print('Second method', i) \
    )

No Python, a sobrecarga não é um conceito aplicado. No entanto, se você estiver tentando criar um caso em que, por exemplo, você quer que um inicializador seja executado se passar um argumento do tipo foo e outro inicializador para um argumento da bar de tipos, pois tudo em Python é tratado como objeto, pode verificar o nome do tipo de classe do objeto passado e escrever tratamento condicional baseado nele.

class A:
   def __init__(self, arg)
      # Get the Argument's class type as a String
      argClass = arg.__class__.__name__

      if argClass == 'foo':
         print 'Arg is of type "foo"'
         ...
      elif argClass == 'bar':
         print 'Arg is of type "bar"'
         ...
      else
         print 'Arg is of a different type'
         ...

Esse conceito pode ser aplicado a vários cenários diferentes por meio de métodos diferentes, conforme necessário.


No arquivo MathMethod.py

from multipledispatch import dispatch
@dispatch(int,int)
def Add(a,b):
   return a+b 
@dispatch(int,int,int)  
def Add(a,b,c):
   return a+b+c 
@dispatch(int,int,int,int)    
def Add(a,b,c,d):
   return a+b+c+d

No arquivo Main.py

import MathMethod as MM 
print(MM.Add(200,1000,1000,200))

Podemos sobrecarregar o método usando multipledispatch


O Python 3.x inclui uma biblioteca de digitação padrão que permite a sobrecarga de métodos com o uso do @overload decorator. Infelizmente, isso é para tornar o código mais legível, já que os métodos decorados @overload precisarão ser seguidos por um método não decorado que manipule argumentos diferentes. Mais pode ser encontrado aqui here mas para o seu exemplo:

from typing import overload
from typing import Any, Optional
class A(object):
    @overload
    def (self) -> None:    
        print('first method')
    @overload
    def (self, i: Any) -> None:
        print('second method', i)
    def (self, i: Optional[Any] = None) -> None:
        if not i:
            print('first method')
        else:
            print('second method', i)

ob=A()
ob.(2)

Você não pode, nunca precisa e realmente não quer.

Em Python, tudo é um objeto. Classes são coisas, então são objetos. Então são métodos.

Existe um objeto chamado A que é uma classe. Tem um atributo chamado . Só pode ter um tal atributo.

Quando você escreve def (...): ... , o que acontece é que você cria um objeto que é o método e o atribui ao atributo de A Se você escrever duas definições, a segunda substitui a primeira, da mesma forma que a atribuição sempre se comporta.

Além disso, você não quer escrever código que seja o mais selvagem dos tipos de coisas que a sobrecarga às vezes é usada. Não é assim que a linguagem funciona.

Em vez de tentar definir uma função separada para cada tipo de coisa que você poderia receber (o que faz pouco sentido, já que você não especifica tipos para parâmetros de função), pare de se preocupar com o que é e comece a pensar no que eles podem fazer .

Você não só não pode escrever um separado para lidar com uma tupla contra uma lista, mas também não quer ou precisa .

Tudo o que você faz é aproveitar o fato de que ambos são, por exemplo, iteráveis ​​(isto é, você pode escrever for element in container: :). (O fato de que eles não são diretamente relacionados por herança é irrelevante.)


Você também pode usar pythonlangutil :

from pythonlangutil.overload import Overload, signature

class A:
    @Overload
    @signature()
    def (self):    
        print 'first method'

    @.overload
    @signature("int")
    def (self, i):
        print 'second method', i

Edit: Com o suporte oficial do Overloading em Python 3 você pode usar o @overload decorator.





overloading