python类继承重复_在python中如何重写类继承来的函数?

一开始还真不是很适应用类(OOP)的思路来组织代码,但慢慢也发现这种方法的好处了。编程高手追求的是更快更少更清晰,即速度更快,代码更少,结构更清晰。采用OOP的代码组织结构,是否能够更快不好说,但是更少和更清晰是很明显的。

类首先是一个namespace,将一堆变量和功能封装起来,更清晰了。通过继承,也实现了代码更少,相同的功能直接继承下来,代码结构呈立体的。在继承类中,如果定义了与父类型相同的函数方法,就算是重定义此函数了,包括__init__函数。在继承类中重定义父类型已有的函数,很多时候我们需要的是扩写,即在原父类型的函数功能基础上,再增加一些代码,这时就需要调用父类型的此函数。本文主要总结这个细节。

直接显示调用父类型的函数

这种方法简单粗暴,也有自己独特的应用场景。

class A:

def out(self, string):

print('In_A_'+string)

class B(A):

def out(self, string):

A.out(self, string)

print('In_B_'+string)

B().out('pynote.net')

B继承A,重写out函数,在out中,首先直接显示调用父类A的out函数,执行效果如下:

D:\py>python super.py

In_A_pynote.net

In_B_pynote.net

这种调用方式,如果所有函数都这样重写,本质上就跟继承没有关系!

请看这段代码:

class A:

def out(self, string):

print('In_A_'+string)

class A2:

def out2(self, string):

print('In_A2_'+string)

class B(A):

def out(self, string):

A2.out2(self, string)

print('In_B_'+string)

B().out('pynote.net')

B继承A,重写out函数,在out中,首先调用的却是一个不相干的类A2的out2函数。执行效果如下:

D:\py>python super.py

In_A2_pynote.net

In_B_pynote.net

这种直接显示调用类型.函数的方式,因为要传递self参数,因此调用的位置是否跟自己有继承关系,就不重要了!这叫直接显示的调用其它不相关类型的函数。但很多时候,因为代码组织,我们看到的都是用这种方式调用自己父类的函数。

这种方式的好处时清晰明了,就算是多继承也有的时候也可以。坏处就是因为是显示先出类名,所以后期代码维护如果类名变化,修改的地方会多一些。

多重继承的问题

上面这种直接显示调用其它类(可以不是父类),逻辑清晰,但是在多重继承的时候,会有点问题。

class A:

def __init__(self):

print("Enter A")

print("Leave A")

class B(A):

def __init__(self):

print("Enter B")

A.__init__(self)

print("Leave B")

class C(A):

def __init__(self):

print("Enter C")

A.__init__(self)

print("Leave C")

class D(A):

def __init__(self):

print("Enter D")

A.__init__(self)

print("Leave D")

class E(B, C, D):

def __init__(self):

print("Enter E")

B.__init__(self)

C.__init__(self)

D.__init__(self)

print("Leave E")

E()

A所有类型的父类,BCD继承A,E继承BCD。他们都重写了__init__方法,而且都是用直接类名.函数的方式调用父类的__init__函数,执行效果如下:

D:\py>python super.py

Enter E

Enter B

Enter A

Leave A

Leave B

Enter C

Enter A

Leave A

Leave C

Enter D

Enter A

Leave A

Leave D

Leave E

问题很明显,A的__init__函数被执行了多次!

使用super函数

上面多重继承带来的问题,可以使用super函数来解决。

class A:

def __init__(self):

print("Enter A")

print("Leave A")

class B(A):

def __init__(self):

print("Enter B")

super().__init__()

print("Leave B")

class C(A):

def __init__(self):

print("Enter C")

super().__init__()

print("Leave C")

class D(A):

def __init__(self):

print("Enter D")

super().__init__()

print("Leave D")

class E(B, C, D):

def __init__(self):

print("Enter E")

super().__init__()

print("Leave E")

E()

继承关系不变,BCDE的__init__函数都采用super()函数。执行效果如下:

D:\py>python super.py

Enter E

Enter B

Enter C

Enter D

Enter A

Leave A

Leave D

Leave C

Leave B

Leave E

E的初始化,不再重复调用A了!

在super机制里,可以保证公共父类仅被执行一次,至于执行的顺序,是按照MRO(Method Resolution Order)方法解析顺序 进行的。

值得注意的是,如果BCD的__init__不使用super函数,就没有上面这个效果。

不能用super的情况

对super的作用,理解还是很肤浅,有点说不清楚,下面这个示例,就不能用super。

class B():

def __init__(self):

print("Enter B")

print("Leave B")

class C():

def __init__(self):

print("Enter C")

print("Leave C")

class D():

def __init__(self):

print("Enter D")

print("Leave D")

class E(B, C, D):

def __init__(self):

print("Enter E")

super().__init__()

print("Leave E")

E()

E继承自BCD,在E的__init__中直接使用super函数。执行效果如下:

D:\py>python super.py

Enter E

Enter B

Leave B

Leave E

显然E只初始化了B,而CD完全没有其作用。网上查到有人说,super主要用在多重继承的情况。还是一头雾水。有人说,使用super可以增加代码的可移植性,比如更换了继承的对象时。

任何在继承类中不重写的函数,包括__init__,都会通过MRO的方式去查找一个有此函数的父类并条用,包括__init__!特别注意初始化函数,一般类都有自己的__init__,多重继承的时候,如果不重写这个函数,一样也只是查找一个有此函数的父类__init__调用。比如下面的代码:

class B():

def __init__(self):

print("Enter B")

print("Leave B")

class C():

def __init__(self):

print("Enter C")

print("Leave C")

class D():

def __init__(self):

print("Enter D")

print("Leave D")

class E(B, C, D): pass

E()

执行效果:

D:\py>python super.py

Enter B

Leave B

-- EOF --

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值