Python方法覆盖,签名是否重要?

问题描述 投票:39回答:6

可以说我有

class Super():
  def method1():
    pass

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

它是否正确?对method1的调用总是会转到子类吗?我的计划是让2个子类重写方法1,使用不同的参数

python inheritance methods override
6个回答
34
投票

Python将允许这样做,但如果method1()旨在从外部代码执行,那么你可能想重新考虑这一点,因为它违反了LSP,所以不会总是正常工作。


12
投票

Python允许使用不同签名的“覆盖”方法,但即使它们的签名不同(即没有方法重载),也不能在同一个类中拥有两个具有相同名称的方法。在覆盖方法的情况下,如果要调用为对象定义的参数数量错误的方法,则会出现错误。请记住,Python的方法只是附加到对象的字典中的键值对,而“覆盖”相当于简单地替换最初从基类字典中复制的相同键的字典中的值。

通常情况下,您希望派生类方法具有除基类之外的其他参数。要在Python中执行此操作同时还要保留LSP,您可以使用以下技术:

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)

以上将打印:

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

Play with this code


1
投票

在python中,所有类方法都是“虚拟的”(就C ++而言)。所以,对于你的代码,如果你想在超类中调用method1(),它必须是:

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

方法签名很重要。你不能调用这样的方法:

sub = Sub()
sub.method1() 

1
投票

它会工作:

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

但是,通常不建议这样做。看看S.Lott的答案:Methods with the same name and different arguments are a code smell


1
投票

如果可以使用默认参数,你可以这样做:

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

-2
投票

是。对“method1”的调用将始终转到子类。 Python中的方法签名只包含名称而不是参数列表。

© www.soinside.com 2019 - 2024. All rights reserved.