Comment utiliser la méthode de surcharge en Python?

j'essaie d'implémenter une méthode de surcharge en Python:

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

ob=A()
ob.stackoverflow(2)

mais la sortie est second method 2 ; de même:

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

ob=A()
ob.stackoverflow()

donne

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

Comment faire pour que ça marche?

116
demandé sur Ethan Furman 2012-04-18 08:47:50

14 réponses

C'est la méthode surcharge pas de méthode substitution . Et en Python, vous faites tout en une seule fonction:

class A:

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

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

vous ne pouvez pas avoir deux méthodes avec le même nom en Python -- et vous n'en avez pas besoin.

voir la section valeurs des arguments par défaut du tutoriel Python. Voir "Least Astonishment" et L'Argument par défaut Mutable pour un erreurs fréquentes à éviter.

Modifier : Voir PEP 443 pour plus d'informations sur le nouveau single de répartition des fonctions génériques en Python 3.4.

124
répondu agf 2017-05-23 12:18:16

en Python, on ne fait pas les choses comme ça. Quand les gens font cela dans des langues comme Java, ils veulent généralement une valeur par défaut (s'ils ne le font pas, ils veulent généralement une méthode avec un nom différent). Ainsi, en Python, vous pouvez avoir des valeurs par défaut .

class A(object):  # Remember the ``object`` bit when working in Python 2.x

    def stackoverflow(self, i=None):
        if i is None:
            print 'first form'
        else:
            print 'second form'

comme vous pouvez le voir, vous can utilisez ceci pour déclencher un comportement séparé plutôt que d'avoir simplement une valeur par défaut.

>>> ob = A()
>>> ob.stackoverflow()
first form
>>> ob.stackoverflow(2)
second form
41
répondu Chris Morgan 2012-04-18 05:02:11

Vous ne pouvez pas, jamais besoin de et ne veulent pas vraiment.

en Python, tout est un objet. Les Classes sont des choses, donc ce sont des objets. Sont donc des méthodes.

il y a un objet appelé A qui est une classe. Il possède un attribut appelé stackoverflow . Il ne peut avoir qu'un seul de ces attributs.

quand vous écrivez def stackoverflow(...): ... , ce qui se passe est que vous créez un objet qui est la méthode, et l'assignez à la stackoverflow attribut de A . Si vous écrivez deux définitions, la deuxième remplace la première, de la même façon que l'affectation se comporte toujours.

vous ne voulez pas non plus écrire de code qui fait le plus sauvage du genre de choses que la surcharge est parfois utilisé pour. Ce n'est pas comme ça que le langage fonctionne.

au lieu d'essayer de définir une fonction séparée pour chaque type de chose que vous pourriez être donné (ce qui n'a pas de sens puisque vous ne spécifiez les types pour les paramètres de fonction de toute façon), arrêter de se soucier de ce que les choses sont et commencer à penser à ce qu'ils peuvent faire .

non seulement vous ne pouvez pas écrire un autre pour gérer un tuple vs. une liste, mais aussi ne veulent pas ou n'ont pas besoin de .

tout ce que vous faites est de profiter du fait qu'ils sont tous les deux, par exemple, itérables (i.e. vous pouvez écrire for element in container: ). (Le fait qu'ils ne soient pas directement liés par héritage n'est pas pertinent.)

28
répondu Karl Knechtel 2017-12-17 00:07:49

vous pouvez également utiliser pythonlangutil :

from pythonlangutil.overload import Overload, signature

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

    @stackoverflow.overload
    @signature("int")
    def stackoverflow(self, i):
        print 'second method', i
26
répondu Ehsan Keshavarzian 2015-04-26 12:11:53

j'écris ma réponse en Python 3.2.1.

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

Comment cela fonctionne:

  1. overload prend n'importe quelle quantité d'appel et les stocke dans tuple functions , puis retourne lambda.
  2. la lambda prend n'importe quelle quantité d'arguments, renvoie ensuite le résultat de la fonction d'appel stockée dans functions[number_of_unnamed_args_passed] appelé avec les arguments passés à la lambda.

Utilisation:

class A:
    stackoverflow=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) \
    )
16
répondu GingerPlusPlus 2017-12-05 15:28:18

je pense que le mot que vous cherchez est "surcharge". Il n'y a pas de méthode de surcharge en python. Vous pouvez cependant utiliser les arguments par défaut, comme suit.

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

Lorsque vous passez un argument, il suivra la logique de la première condition et exécuter la première instruction print. Lorsque vous le passez sans argument, il va dans la condition else et exécutera la seconde instruction d'impression.

12
répondu mayhewr 2012-04-18 04:54:54

j'écris ma réponse en Python 2.7:

en Python, la surcharge de la méthode n'est pas possible; si vous voulez vraiment accéder à la même fonction avec des fonctionnalités différentes, je vous suggère d'opter pour la méthode overriding.

class Base(): # Base class
    '''def add(self,a,b):
        s=a+b
        print s'''

    def add(self,a,b,c):
        self.a=a
        self.b=b
        self.c=c

        sum =a+b+c
        print sum

class Derived(Base): # Derived class
    def add(self,a,b): # overriding method
        sum=a+b
        print sum



add_fun_1=Base() #instance creation for Base class
add_fun_2=Derived()#instance creation for Derived class

add_fun_1.add(4,2,5) # function with 3 arguments
add_fun_2.add(4,2)   # function with 2 arguments
12
répondu Moorthi Muthu 2016-03-19 23:18:36

en Python, la surcharge n'est pas un concept appliqué. Cependant, si vous essayez de créer un cas où, par exemple, vous voulez qu'un initialiseur soit exécuté si passé un argument de type foo et un autre initialiseur pour un argument de type bar alors, puisque tout en Python est traité comme objet, vous pouvez vérifier le nom du type de classe de l'objet passé et écrire la manipulation conditionnelle basée sur cela.

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'
         ...

ce concept peut être appliqué à plusieurs scénarios différents au moyen de différentes méthodes, au besoin.

9
répondu S. Gamgee 2016-09-26 21:30:08

en Python, vous le feriez avec un argument par défaut.

class A:

    def stackoverflow(self, i=None):    
        if i == None:
            print 'first method'
        else:
            print 'second method',i
7
répondu John Gaines Jr. 2012-04-18 04:55:29

vient de tomber sur ce https://github.com/bintoro/overloading.py pour tous ceux qui pourraient être intéressés.

D'après readme du dépôt lié:

overloading est un module qui fournit la fonction dispatching basé sur les types et le nombre d'arguments runtime.

Lorsqu'une fonction surchargée est invoquée, le répartiteur compare arguments fournis à disponible signature et appel de la fonction mise en œuvre qui fournit la correspondance la plus précise.

Caractéristiques

validation de la fonction lors de l'enregistrement et règles de résolution détaillées garantir un résultat unique et bien défini à l'exécution. Mettre cache de résolution de fonction pour de grandes performances. Prise en charge facultative paramètres (valeurs par défaut) dans les signatures de fonction. Évalue à la fois arguments de position et de mots clés lors de la résolution du meilleur correspondre. Prend en charge les fonctions de repli et l'exécution du code partagé. Soutien l'argument de polymorphisme. Soutient les classes et l'héritage, y compris classeméthodes et méthodes statiques.

5
répondu Mark Lawrence 2015-02-06 21:13:10

Python ne supporte pas les méthodes de surcharge comme Java ou C++. Nous pouvons surcharger les méthodes mais ne pouvons utiliser que la dernière méthode définie.

# First sum method.
# Takes two argument and print their sum
def sum(a, b):
    s = a + b
    print(s)

# Second sum method
# Takes three argument and print their sum
def sum(a, b, c):
    s = a + b + c
    print(s)

# Uncommenting the below line shows an error    
# sum(4, 5)

# This line will call the second sum method
sum(4, 5, 5)

nous devons fournir des arguments optionnels ou *args afin de fournir un nombre différent d'args sur appel.

gracieuseté de https://www.geeksforgeeks.org/python-method-overloading /

3
répondu Atihska 2018-07-25 20:42:12

alors que @agf avait raison avec la réponse dans le passé maintenant avec PEP-3124 nous avons eu notre sugger de syntaxe. Voir documentation de Dactylographie pour plus de détails sur le @overload décorateur, mais notez que c'est vraiment la syntaxe sugger et IMHO tout ce que les gens ont été discuter depuis. Personnellement, je suis d'accord que d'avoir plusieurs fonctions avec des signatures différentes le rend plus lisible que d'avoir une seule fonction avec 20 + arguments tous mis à une valeur par défaut ( None la plupart du temps) et de devoir bricoler autour de l'utilisation sans fin if , elif , else chaînes pour savoir ce que l'appelant veut réellement notre fonction à faire avec l'ensemble fourni d'arguments. Ceci, est attendu depuis longtemps suite au Zen de Python

beau est mieux que laid.

et sans doute aussi

Simple est mieux que complexe.

directement de la documentation officielle de Python liée ci-dessus:

@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>
2
répondu masi 2018-09-23 16:27:48

In MathMethod.py dossier

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

In Main.py dossier

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

On peut surcharger une méthode en utilisant multipledispatch

0
répondu Mahabubuzzaman 2018-04-23 08:46:36

Python 3.x comprend une bibliothèque de Dactylographie standard qui permet la surcharge de la méthode avec l'utilisation de @ overload decorator. Malheureusement, c'est pour rendre le code plus lisible, car les méthodes décorées @overload devront être suivies par une méthode non décorée qui gère différents arguments. Plus peut être trouvé ici ici mais pour votre exemple:

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

ob=A()
ob.stackoverflow(2)
0
répondu nickthefreak 2018-10-10 15:49:20