写在前面的话html
终于,又到了周五。当小伙伴们都再也不加班欢欢喜喜过周末的时候,我刚刚写完这一周的游戏做业,从面对晚归的紧皱眉头到如今的从容淡定,好像只有那么几周的时间。忽然发现:改变——原来这么简单。不少时候咱们在想要为本身的青春拼搏一次的时候都输给了偶尔的抵触和轻松愉悦的生活。咱们不过和走到最后的人差了两个字——坚持!因此尽管进入类和对象这一部分,你们都会有畏难心理,可是坚持一下下,你就会是那个走到最后的人!python
回顾 程序员
上一篇中咱们初步的认识了类和对象,告终了它们的一些语法,就至关于获得了一个对象的骨骼。今天再来补充一些和他们相关的内容,给咱们的小骷髅添上肌肉和皮肤,它就是一个活生生的对象了,今后你也是一个有对象的人了!哈~ide
首先咱们从面向对象的特性这个角度先回顾一下上一篇的内容,以前咱们已经知道了“车”是一个类,车的“品牌”和“价格”是它的属性,能够在路上跑是他的行为;所以咱们定义了一个类car,并在这个car类中定义了price和type两个属性,还有一个DriveDistance方法。咱们说,这个car类就像是一个收纳包,把和“车”有关的零散属性、方法都装进了包里,这就是面向对象的封装性。ui
面向对象的三大特性spa
上一篇咱们讲的主要内容都符合面向对象的封装特性。那么问题来了?面向对象难道只有封装性么?固然不是,做为一个这么难理解的东西,要是只有封装性都对不起咱们死了这么多脑细胞!因此,晴天霹雳来了,面向对象有三大特性,他们分别是:封装、继承和多态。code
好消息和好消息和好消息,好消息一:封装咱们已讲完,因此三座大山咱们已经移走了一座,好消息二:因为python的特殊性,多态的应用并不普遍,因此咱们其实还有一座半就胜利了,好消息三:前面那两条好消息都是真的。闲话少叙,今天我们就聊聊继承,移走一座是一座!htm
正题——面向对象的继承性对象
1、继承blog
大学同窗聚会,同桌吃饭,咱们都是人,都有吃饭、喝饮料这些行为,可是毕业以后你们都作了不一样的工做,有的当了会计、有的作了程序员,如今咱们获得了描述这些同窗这个需求,咱们一看很是开心,咱们能够实现呀,而后写下了下面左图的代码:
咱们看上面左侧的代码,这么写确实实现了咱们的需求,可是,写了那么多行,真正不同的只有黄色框框里面的内容,好在大学同窗的职业都差很少,这要是高中聚会可就热闹了。这个时候,咱们就想,有没有可能咱们不重复写以前的代码,也实现一样的功能呢?固然啦!→_→右侧这段代码。看着就简洁了很多,这就是类的继承。如今你看着好像有点儿迷糊,不要紧,这里只须要知道有一种简单的方法能够实现,这种写法就叫作继承。具体咱们后面还要详细讲。
咱们来详细看看上面这张图,解释一下什么叫作继承,首先在最上面的黄框框里,咱们定义了一个类叫作classmate,这个里面放了吃、喝两个方法,下面咱们又定义了两个类,pythoner和accounting类,里面各写了一个occupation方法,打印出了人物的职业。咱们看到,classmate类和咱们以前见到的类并没什么不一样,但是pythoner和accounting类定义的时候,咱们看红框框里写了classmate类的类名,咱们说,这样就实现了继承。pythoner和accounting类集成了classmate的全部属性和方法。
说完了继承类的定义,咱们再来看看实例化和调用,咱们看上面右侧那张小图,咱们分别实例化了两个对象,eva和sweet,注意看红框框里咱们实例化的是pythoner和accounting这两个派生类,可是咱们却能够调用classmate的eat和drink方法,并且咱们在occupation中也可使用父类的name属性。magic!代码在下面~
1 class classmate(): 2 def __init__(self,name): 3 self.name = name 4 def eat(self): 5 print '%s is eating.'%self.name 6 def drink(self): 7 print '%s is drinking'%self.name 8 9 10 class pythoner(classmate): 11 def occupation(self): 12 print '%s is a pythoner.'%self.name 13 14 class accounting(classmate): 15 def occupation(self): 16 print '%s is a accounting.'%self.name 17 18 eva = pythoner('eva') 19 eva.occupation() 20 eva.eat() 21 eva.drink() 22 23 sweet = accounting('sweet') 24 sweet.occupation() 25 sweet.eat() 26 sweet.drink()
2、多继承
如今咱们基本可使用类的继承描述同坐一桌的同窗们了,可是咱们如今又有了一个新需求,就是把这一桌的男生和女生分开,男生喝酒,女生喝饮料,这个需求怎么用类来区别呢?先上图~
咱们看上面左侧这张图,因为需求的增长,要求把同桌的男生和女生分开,我又新写了两个female和male类从新定义drink方法,而且又定义了新的类fe_pythoner和ma_pythoner,因此这两个类什么也不作,只是分别继承female、classmate和male、classmate类。在实例化对象的时候咱们使用fe_pythoner和ma_pythoner,咱们这样猜测,这个时候对象eva和sweet是否是应该分别去调用female和male中的drink方法呢?执行下,看看下面的结果。什么鬼?居然仍是输出了基类的drink方法。再看看右边,没错,我只是在定义基类的时候让基类继承了object,它就能够按照咱们想要的方法输出了。
3、经典类的深度优先和新式类的广度优先
那么原理是什么呢?这个时候我就要盗一张图来解释这个问题了:
咱们看上面的图,先放两句概念上来吓唬吓唬你:
那么什么是经典类和新式类呢?简而言之,继承自object的类就叫作新式类,object类是python提供的,如今咱们还不须要管它从哪里来,由于让类中的不少操做变得更合理了,咱们之后记着就这么写就对了。注:下面小伙伴提到,python3.X版本中的类继承默认就是广度优先。
下面来讲广度优先和深度优先,首先,B和C两个类都必须继承自D,A类又继承自B、C,就是针对这种状况,没有为何。。。背下来!咱们对应起来看,这里的基类D就是上例中的classmate,BC就是pythoner和female,A则对应fe_pythoner类。
经典类中:当咱们这样写:fe_pythoner(pythoner,female),对象调用方法的时候,会先在fe_pythoner里面找,而后依次去找pythoner、classmate、最后再找female。若是找到了,就会执行,而且再也不继续找下去了。因此咱们刚刚在左侧举出得栗子中它先找到了classmate中的drink方法,才打印出了一样的内容。这就是深度优先。
新式类中:当咱们这样写:fe_pythoner(pythoner,female),对象调用方法的时候,会先在fe_pythoner里面找,而后依次去找pythoner、female、最后再找classmate。若是找到了,就会执行,而且再也不继续找下去了。因此咱们刚刚在右侧举得栗子中它先找到了female、或male中的drink方法,就打印了不一样的内容。这就是广度优先。
1 class classmate(object): 2 def __init__(self,name): 3 self.name = name 4 5 def eat(self): 6 print '%s is eating.'%self.name 7 8 def drink(self): 9 print '%s is drinking'%self.name 10 11 class female(classmate): 12 13 def drink(self): 14 print '%s drink orange juice'%self.name 15 16 class male(classmate): 17 18 def drink(self): 19 print '%s drink alcohol'%self.name 20 21 class pythoner(classmate): 22 23 def occupation(self): 24 print '%s is a pythoner.'%self.name 25 26 27 28 class fe_pythoner(pythoner,female): 29 pass 30 class male_pythoner(pythoner,male): 31 pass 32 33 eva = fe_pythoner('eva') 34 eva.drink() 35 36 sweet = male_pythoner('sweet') 37 sweet.drink()
若是上面那些你统统没搞清楚,也不要紧,在继承的时候能够直接把female类写在前面 fe_pythoner(female,pythoner),这么一来无论怎么样,都是先找female了。
好了,到如今为止咱们如今已经移走了面向对象的第二座大山,离胜利又进了一步,感谢努力的本身,又多坚持了一下~~~