Python方法重写,签名重要吗?

2024-05-19 20:12:22 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有

class Super():
  def method1():
    pass

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

这是对的吗?调用method1总是转到子类吗?我的计划是有两个子类,每个子类用不同的参数重写method1


Tags: 参数defpass子类计划classparam1super
3条回答

Python将允许这样做,但是如果method1()打算从外部代码执行,那么您可能需要重新考虑这一点,因为它违反了LSP,因此不会总是正常工作。

在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() 

在Python中,方法只是附加到类的字典中的键值对。当您从基类派生类时,实际上是说方法名将首先在派生类字典中查找,然后在基类字典中查找。为了“重写”方法,只需在派生类中重新声明该方法。

那么,如果在派生类中更改重写方法的签名呢?如果调用在派生实例上,则一切正常工作,但如果对基实例进行调用,则会得到错误,因为基类对同一方法名使用不同的签名。

但是,在很多情况下,您希望派生类方法具有附加的参数,并且希望方法调用在基本上不会出错。这被称为“Liskov替换原则”(或者LSP),它保证如果用户从基实例切换到派生实例,或者反过来,他们不必修改代码。要在Python中执行此操作,需要使用以下技术设计基类:

class Base:
    # simply allow additional args in base class
    def hello(self, name, *args, **kwargs):
        print("Hello", name)

class Derived(Base):
      # derived class also has unused optional args so people can
      # derive new class from this class as well while maintaining LSP
      def hello(self, name, age=None, *args, **kwargs):
          super(Derived, self).hello(name, age, *args, **kwargs) 
          print('Your age is ', age)

b = Base()
d = Derived()

b.hello('Alice')        # works on base, without additional params
b.hello('Bob', age=24)  # works on base, with additional params
d.hello('Rick')         # works on derived, without additional params
d.hello('John', age=30) # works on derived, with additional params

上面将打印:

    Hello Alice
    Hello Bob
    Hello Rick
    Your age is  None
    Hello John
    Your age is  30
Play with this code

相关问题 更多 >