web-dev-qa-db-fra.com

Python Méthode prioritaire, la signature est-elle importante?

Disons que j'ai

class Super():
  def method1():
    pass

class Sub(Super):
  def method1(param1, param2, param3):
      stuff

Est-ce correct? Les appels à method1 iront-ils toujours à la sous-classe? Mon plan est d'avoir 2 sous-classes chaque méthode override1 avec différents paramètres

44
asdasasdsa

Python le permettra, mais si method1() est destiné à être exécuté à partir de code externe, vous voudrez peut-être reconsidérer cela, car il viole LSP = et ne fonctionnera donc pas toujours correctement.

34

Python permet de "remplacer" les méthodes avec des signatures différentes mais vous ne pouvez jamais avoir deux méthodes avec le même nom dans la même classe même si leurs signatures sont différentes (c'est-à-dire pas de surcharge de méthode). En cas de substitution de méthode, si vous appelez des méthodes avec un nombre incorrect de paramètres définis pour l'objet, vous obtiendrez une erreur. Rappelez-vous, les méthodes de Python ne sont que des paires clé-valeur dans le dictionnaire attachées à l'objet et "remplacer" revient simplement à remplacer la valeur dans ce dictionnaire copiée initialement à partir du dictionnaire de la classe de base pour la même clé.

Il existe fréquemment des scénarios dans lesquels vous souhaitez que la méthode de classe dérivée ait des paramètres supplémentaires que la classe de base. Pour ce faire dans Python tout en préservant également LSP , vous pouvez utiliser la technique suivante:

class Base:
    def hello(self, name, *kargs, **kwargs):
        print("Hello", name)

class Derived(Base):
      def hello(self, name, age=None, *kargs, **kwargs):
          super(Derived, self).hello(name, age, *kargs, **kwargs) 
          print('Your age is ', age)

b = Base()
d = Derived()

b.hello('Alice')
b.hello('Bob', age=24)
d.hello('Rick')
d.hello('John', age=30)

Ci-dessus imprimera:

Hello Alice
Hello Bob
Hello Rick
Your age is  None
Hello John
Your age is  30

Jouez avec ce code

12
Shital Shah

En python, toutes les méthodes de classe sont "virtuelles" (en termes de C++). Donc, dans le cas de votre code, si vous souhaitez appeler method1() en super classe, cela doit être:

class Super():
    def method1(self):
        pass

class Sub(Super):
    def method1(self, param1, param2, param3):
       super(Sub, self).method1() # a proxy object, see http://docs.python.org/library/functions.html#super
       pass

Et la signature de la méthode est importante. Vous ne pouvez pas appeler une méthode comme celle-ci:

sub = Sub()
sub.method1() 
1
Zaur Nasibov

Ça va marcher:

>>> class Foo(object):
...   def Bar(self):
...     print 'Foo'
...   def Baz(self):
...     self.Bar()
... 
>>> class Foo2(Foo):
...   def Bar(self):
...     print 'Foo2'
... 
>>> foo = Foo()
>>> foo.Baz()
Foo
>>> 
>>> foo2 = Foo2()
>>> foo2.Baz()
Foo2

Cependant, ce n'est généralement pas recommandé. Jetez un oeil à S.Lott réponse: Les méthodes avec le même nom et des arguments différents sont une odeur de code .

1
quasistoic

Vous pouvez faire quelque chose comme ceci si vous pouvez utiliser des arguments par défaut:

>>> class Super():
...   def method1(self):
...     print("Super")
...
>>> class Sub(Super):
...   def method1(self, param1="X"):
...     super(Sub, self).method1()
...     print("Sub" + param1)
...
>>> sup = Super()
>>> sub = Sub()
>>> sup.method1()
Super
>>> sub.method1()
Super
SubX
1
Zitrax