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?
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.
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
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.)
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
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:
-
overload
prend n'importe quelle quantité d'appel et les stocke dans tuplefunctions
, puis retourne lambda. - 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) \
)
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.
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
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.
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
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.
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 /
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>
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
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)