asd*_*dsa 48 python methods inheritance overriding
可以说我有
class Super():
def method1():
pass
class Sub(Super):
def method1(param1, param2, param3):
stuff
Run Code Online (Sandbox Code Playgroud)
它是否正确?对method1的调用总是会转到子类吗?我的计划是让2个子类重写方法1,使用不同的参数
Ign*_*ams 35
Python将允许这样做,但如果method1()
打算从外部代码执行,那么您可能需要重新考虑这一点,因为它违反了LSP,因此无法始终正常工作.
Shi*_*hah 16
在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
Run Code Online (Sandbox Code Playgroud)
上面将打印:
你好爱丽丝 你好鲍勃 你好里克 你的年龄是无 你好约翰 你30岁。 玩这个代码
在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
Run Code Online (Sandbox Code Playgroud)
方法签名确实很重要。你不能调用这样的方法:
sub = Sub()
sub.method1()
Run Code Online (Sandbox Code Playgroud)