web-dev-qa-db-fra.com

Méthodes avec le même nom dans une classe en python?

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
34
user278618

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
52
kefeizhou

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.

21
user395760

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
4
SteveMc

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.

1
gruszczy

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.

0
Hubert Kario
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
0
sudokode

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

0
mripard

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
0
bbrame