设为首页 收藏本站
查看: 982|回复: 0

[经验分享] Learn Python The Hard Way学习(44)

[复制链接]

尚未签到

发表于 2017-5-6 06:05:20 | 显示全部楼层 |阅读模式
balabala...讲了一个故事,就不翻译了。



只要记着:我们要尽量简单的使用继承,或者用组合代替继承,而且做好不要使用多继承。




什么是继承?

继承被用来指明一个类可以从它的父类取得大部分或者全部的特征。当你写class Foo(Bar)的时候,继承就发生了。Foo类的实例和Bar类的实例一样工作。继承就是为了你能再Bar类中定义普通的方法,而在Foo类中定义特殊的方法。




当做了继承后,父类和子类有三个相互影响的方法:


  • 子类的动作暗含了父类的动作
  • 子类的动作覆盖了相应的父类动作
  • 子类的动作改变了相应的父类动作

暗含继承



先在父类定义一个implicit函数,子类什么也不做。

class Parent(object):

def implicit(self):
print "parent implicit()"

class Child(Parent):
pass

dad = Parent()
son = Child()
dad.implicit()
son.implicit()






在子类中使用pass就是告诉python,这里是一个空的代码块。就是说子类完全继承父类的特征。运行代码的结果如下:

parent implicit()

parent implicit()






注意,我调用了son.implicit()在16行,但是子类并没有这个方法,它调用了父类的对应方法执行。这里告诉你,子类会自动取得父类的所有特征,不需要重复编写代码。




覆盖暗含

问题是有时候你希望子类继承的函数有不同的提现,解决办法就是覆盖父类的函数,定义一个同名的函数在子类中,代码如下:

class Parent(object):

def override(self):
print "parent override()"

class Child(Parent):

def override(self):
print "child override()"

dad = Parent()
son = Child()
dad.override()
son.override()






运行效果如下:

parent override()

child override()






正如你看到的,子类运行相应的函数的时候会运行覆盖过的函数,相当于子类的新版本。




改变之前或者之后

改变和覆盖有一些区别,我们需要先覆盖父类的函数,然后再通过super调用父类的函数,在调用的前后可以添加其他方法,例如如下:

class Parent(object):

def altered(self):
print "parent altered()"

class Child(Parent):

def altered(self):
print "child, before parent altered()"
super(Child, self).altered()
print "child, after parent altered()"

dad = Parent()
son = Child()
dad.altered()
son.altered()






第9和11行比较重要,当我调用son.altered()的时候做了下面这些事情:


  • 因为我已经覆盖了父类的函数altered,所以第9行会在子类调用altered的时候执行。
  • 我希望在第9行后执行父类的altered,所以我使用了super。
  • 在第10行我调用super(child, self).altered(),有点像不久前使用的getattr函数,不过这里是从继承的父类那里调用函数。
  • 然后,父类的函数运行,并打印信息。
  • 最后,从父类函数返回,继续运行剩下的子类的语句。

运行结果如下:



parent altered()

child, before parent altered()

parent altered()

child, after parent altered()






混合使用三个方法

class Parent(object):

def implicit(self):
print "parent implicit()"

def override(self):
print "parent override()"

def altered(self):
print "parent altered()"

class Child(Parent):

def override(self):
print "child override()"

def altered(self):
print "child, before parent altered()"
super(Child, self).altered()
print "child, after parent altered()"

dad = Parent()
son = Child()
dad.implicit()
son.implicit()
dad.override()
son.override()
dad.altered()
son.altered()






给代码加上注释,区别这三种方式,运行如下:

parent implicit()

parent implicit()

parent override()

child override()

parent altered()

child, before parent altered()

parent altered()

child, after parent altered()






使用super()的理由

现在有个麻烦,就是多重继承,意思是一个类继承了多个类,像下面这样:

class SuperFun(Child, BadStuff):

  pass




就像是说:”创建一个SuperFun,同时继承Child和BadStuff类。




这样的话,当SuperFun实例有隐含的动作的时候,python需要去两个类中取寻找,这就必须有一定的顺序。Python使用一个叫“Method
Resolution Order”(MRO)和C3算法实现。




由于MRO很复杂,Python不可能让你直接使用它,所以给了一个super方法让你调用,使用后python会自动实现内部的调用。




在__init__中使用super()

通常super()都是在__init__中使用的,完成父类的初始化,下面是一个例子:

class Child(Parent):

  def __init__(self, stuff):

    self.stuff = stuff

    super(Child, self).__init__()




组成

继承很有用,但是另外一个方法可以使用类和模块最相同的事情,而不依赖隐含继承。下面这种方法可以简单的实现上面那三种方式。看例子:

class Other(object):
def override(self):
print "other override()"

def implicit(self):
print "other implicit()"

def altered(self):
print "other altered()"

class Child(object):
def __init__(self):
self.other = Other()

def implicit(self):
self.other.implicit()

def override(self):
print "child override()"

def altered(self):
print "child, before other altered()"
self.other.altered()
print "child, after other altered()"

son = Child()
son.implicit()
son.override()
son.altered()






上面的代码我没有用Parent,以免产生is-a关系的误解,运行如下:

other implicit()

child override()

child, before other altered()

other altered()

child, after other altered()






你可以看到上面的代码完成了相同的功能。唯一不同的是我必须定义一个Child.implicit的函数。现在我可以说,我需要Other类的话,只要把它写到other.py文件中,然后通过模块调用就好了。




什么时候用继承,什么时候用组合

不管是继承还是组合,都是为了解决问题,继承可以让你继承父类的特征,组合可以让你简单的从其他类中调用函数。




他们都是解决重复使用的问题,到底用哪一个合适呢?这个问题是很主观的,不管我给出了我自己的三条规则:


  • 不要使用多重继承,它太复杂了。一定要用的话,必须清楚的了解它。
  • 使用组合打包你的代码,它可以在其他无关的地方使用你打包好的模块。
  • 在非常明确的复用代码情况下才使用继承。

不管怎么样,不要墨守成规,你可以在工作中和同事制定你们自己的规则,能很好的解决问题就可以了。






加分练习

这里只有一个加分练习,因为这个练习比较大,去看看http://www.python.org/dev/peps/pep-0008/并且用到你的代码中。你会发现和我们书上说的不太一样,不过现在你必须去理解它的描述并且用到你的代码中。用了以后可能会让代码有点混乱,不过你必须理解它的重要性,这是一种好的规范。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-373526-1-1.html 上篇帖子: Python核心编程之正则表达式-练习题解答 下篇帖子: python与tkinter结合写的简易相册预览(原创)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表