Comment déclarer quelques méthodes avec le même nom, mais avec des nombres de paramètres ou des types différents dans une même classe?
Ce que je dois changer dans cette classe:
class MyClass:
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
def my_method(self,parameter_A_that_Must_Be_String):
print parameter_A_that_Must_Be_String
def my_method(self,parameter_A_that_Must_Be_String,parameter_B_that_Must_Be_String):
print parameter_A_that_Must_Be_String
print parameter_B_that_Must_Be_String
def my_method(self,parameter_A_that_Must_Be_String,parameter_A_that_Must_Be_Int):
print parameter_A_that_Must_Be_String * parameter_A_that_Must_Be_Int
Vous pouvez avoir une fonction qui prend un nombre variable d'arguments.
def my_method(*args, **kwds):
# do something
# when you call the method
my_method(a1, a2, k1=a3, k2=a4)
# you get:
args = (a1, a2)
kwds = {'k1':a3, 'k2':a4}
Vous pouvez donc modifier votre fonction comme suit:
def my_method(*args):
if len(args) == 1 and isinstance(args[0], str):
# case 1
Elif len(args) == 2 and isinstance(args[1], int):
# case 2
Elif len(args) == 2 and isinstance(args[1], str):
# case 3
Tu ne peux pas. Il n'y a pas de surcharges, de méthodes multiples ou de choses similaires. Un nom fait référence à une chose. En ce qui concerne la langue de toute façon, vous pouvez toujours les émuler vous-même ... Vous pourriez vérifier les types avec isinstance
(mais veuillez le faire correctement - par exemple, en Python 2, utilisez basestring
pour détecter les chaînes et l'unicode), mais c'est moche, généralement découragé et rarement utile. Si les méthodes font des choses différentes, donnez-leur des noms différents. Considérons également le polymorphisme.
Réponse courte: vous ne pouvez pas ( voir cette discussion précédente ). En général, vous utiliseriez quelque chose comme (vous pouvez ajouter plus de vérification de type et de réorganisation):
def my_method(self,parameter_A, parameter_B=None):
if isinstance(parameter_B, int):
print parameter_A * parameter_B
else:
print parameter_A
if parameter_B is not None:
print parameter_B
Vous pouvez essayer plusieurs méthodes en Python:
http://www.artima.com/weblogs/viewpost.jsp?thread=101605
Mais je ne crois pas que la multi-méthode soit une voie à suivre. Les objets que vous transmettez à une méthode doivent avoir une interface commune. Vous essayez d’obtenir une surcharge de méthode semblable à celle de C++, mais elle est très rarement requise en python. Une façon de le faire est d'utiliser une cascade de ifs
utilisant isinstance
, mais c'est moche.
Je pense qu'un exemple très simple manque dans toutes les réponses, à savoir: que faire lorsque la seule différence entre les variations de la méthode est le nombre d'arguments. La réponse est toujours d'utiliser une méthode avec un nombre variable d'arguments.
Dis, tu commences avec une méthode qui nécessite l'utilisation de deux arguments
def method(int_a, str_b):
print("Got arguments: '{0}' and '{1}'".format(int_a, str_b)
alors vous devez ajouter une variante avec seulement le deuxième argument (par exemple, parce que l'entier est redondant), la solution est très simple:
def _method_2_param(int_a, str_b):
print("Got arguments: '{0}' and '{1}'".format(int_a, str_b))
def _method_1_param(str_b):
print("Got argument: '{0}'".format(str_b))
def method(*args, **kwargs):
if len(args) + len(kwargs) == 2:
return _method_2_param(args, kwargs)
Elif len(args) + len(kwargs) == 1:
return _method_1_param(args, kwargs)
else:
raise TypeError("Method requires one or two arguments")
La bonne chose à propos de cette solution est que peu importe si le code appelant utilisait auparavant des arguments de mots clés ou des arguments de position, il continuera de fonctionner.
class MyClass:
def __init__(this, foo_str, bar_int):
this.__foo = foo_str
this.__bar = bar_int
def foo(this, new=None):
if new != None:
try:
this.__foo = str(new)
except ValueError:
print("Illegal value. foo unchanged.")
return this.__foo
def bar(this, new=None):
if new != None:
try:
this.__bar = int(new)
except ValueError:
print("Illegal value. bar unchanged.")
return this.__bar
obj = MyClass("test", 42)
print(obj.foo(), obj.bar())
print(obj.foo("tset"), obj.bar(24))
print(obj.foo(42), obj.bar("test"))
Output:
test 42
tset 24
Illegal value. bar unchanged.
42 24
Python n'a rien à voir avec Java.
Il n'y a pas vraiment de types, juste des objets avec des méthodes.
Il existe un moyen de tester si un objet transmis provient d'une classe, mais il s'agit principalement de mauvaises pratiques.
Cependant, le code que vous voulez générer pour les deux premières méthodes devrait ressembler à
class MyClass(object):
def my_method(self, str1, str2=None):
print str1
if str2: print str2
Pour le troisième, eh bien ... Utilisez un nom différent ...
Vous voulez probablement un modèle semblable au suivant:
class MyClass:
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
def my_method(self,parameter_A_that_Must_Be_String, param2=None):
if type(param2) == str:
return self._my_method_extra_string_version(parameter_A_that_Must_Be_String, param2)
Elif type(param2) == int:
return self._my_method_extra_int_version(parameter_A_that_Must_Be_String, param2)
else:
pass # use the default behavior in this function
print parameter_A_that_Must_Be_String
def _my_method_extra_string_version(self,parameter_A_that_Must_Be_String, parameter_B_that_Must_Be_String):
print parameter_A_that_Must_Be_String
print parameter_B_that_Must_Be_String
def _my_method_extra_int_version(self,parameter_A_that_Must_Be_String, parameter_A_that_Must_Be_Int):
print parameter_A_that_Must_Be_String * parameter_A_that_Must_Be_Int