Python面向对象编程(二)
1.继承与派生
上文我们已经说过,Python中一切皆对象。我们从对象中抽取了共同特征和技能,得到了类的概念。类与类之间也有共同特征,我们可以从有共同特征和技能的类中提取共同的技能和特征,叫做父类。
比如老师和学生,都有名字,年纪,生日,性别等等,都会走,说话,吃饭。。。我们就可以从老师和学生中总结出来一个‘人’类,称为父类,那老师和学生就是‘人’类的子类,子类继承父类,就有了父类的特征和方法。
继承是一种什么‘是’什么的关系,继承是一种产生新类的方法,当然目的也是为了减少代码重用。
继承的 基本形式是:
class People:
pass
class Student(People):#People称为基类或者父类
pass
在Python中支持多继承,一个子类可以继承多个父类
我们可以通过__bases__的方法查看继承的所有父类,会返回一个元组。
class People:
pass
class Animals:
pass
class Student(People,Animals):
pass print(Student.__bases__)#(<class '__main__.People'>, <class '__main__.Animals'>)
print(People.__bases__)#(<class 'object'>,)
可以看到,在People父类中,默认也继承了一个object类,这就是新式类和经典类的区别:
凡是继承了object类的类及其子类,都称为新式类,没有继承object类的类,称为经典类。
在Python 3中,默认就是新式类,而在Python2.X中,默认都是是经典类
继承怎么减少代码呢?看例子
class People:
def __init__(self,name,age):
self.name=name
self.age=age
def walk(self):
print('%s is walkig'%self.name) class Teacher(People):
def __init__(self,name,age,level):
People.__init__(self,name,age)
self.level=level t1=Teacher('zhang',18,10)
print(t1.level) #
print(t1.name) #zhang 子类可以用父类定义的属性
t1.walk() #zhang is walking 子类无需定义就可以用父类的方法
print(issubclass(Teacher,People)) #True查看Teacher类是不是People类的子类
从上面的例子中可以看到,Teacher类继承了父类People类,但是Teacher又有自己特有的属性level,子类也可以定义自己独有的方法,甚至可以和父类的方法重名,但是执行时会以子类定义的为准。
这就叫做派生
2.组合
继承是解决什么‘是’什么的问题,那还有一种场景就是什么有什么,比如老师有生日,学生也有生日,生日有年月日这些属性,如果每个类都写的话,又是重复代码。但是又不能让学生和老师继承生日类。这时就用到了组合。组合就是解决什么‘有’什么的问题。看例子
class Date:
def __init__(self,year,mon,day):
self.year=year
self.mon=mon
self.day=day
def tell_birth(self):
print('出生于%s年%s月%s日'%(self.year,self.mon,self.day)) class Teacher:
def __init__(self,name,age,year,mon,day):
self.name=name
self.age=age
self.birth=Date(year,mon,day)
t=Teacher('egon',19,2010,10,10)
print(t.birth) #<__main__.Date object at 0x0000017E559380F0>
t.birth.tell_birth() #出生于2010年10月10日
什么?嫌参数太多?*args学过吧,你高兴就好
class Date:
def __init__(self,year,mon,day):
self.year=year
self.mon=mon
self.day=day
def tell_birth(self):
print('出生于%s年%s月%s日'%(self.year,self.mon,self.day)) class Teacher:
def __init__(self,name,age,*args):
self.name=name
self.age=age
self.birth=Date(*args)
t=Teacher('egon',19,2010,10,10)
print(t.birth) #<__main__.Date object at 0x0000017E559380F0>
t.birth.tell_birth() #出生于2010年10月10日
3.抽象类与接口
继承有两种用途:1.代码重用,子类继承父类的方法
2.声明某个子类兼容于某父类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能
需要注意的是,Python中并没有接口的关键字,我们只能是模仿接口的功能
比如在 Python中,一切皆文件嘛,那程序是文件,硬件是文件,文本文档也是文件,我们知道什么叫文件呢,就是能读能写,那程序,文本文档这些,都应该有读和写的功能,我们来模拟一下
class Interface:
def read(self):
pass
def write(self):
pass class Txt(Interface):
def read(self):
print('文本文档的读取方式')
def write(self):
print('文本文档的写入方式') class Sata(Interface):
def read(self):
print('硬盘文件的读取方式')
def write(self):
print('硬盘文件的写入方式') class process(Interface):
def read(self):
print('进程数据的读取方式')
def write(self):
print('进程数据的写入方式')
这么做的意义就是:我们不需要知道子类有什么具体的方法,既然他们继承了文件类,那他们就是文件,那他们就有读和写这两个功能
父类限制了子类子类必须有read和write这两个方法,而且名字也必须一样(当然现在只是我们主观上的限制,一会我们说完抽象类,就可以从代码级别上限制了),这样就实现了统一,模拟了接口的概念,这就是归一化设计。在归一化设计中,只要是基于一个接口设计的类,那么所有的这些类实例化出来的对象,在用法上是一样的
我们再来说一下抽象类:
Python中的抽象类需要导入一个模块来实现。抽象类只能被继承,不能被实现
抽象类的写法:
import abc
class File(metaclass=abc.ABCMeta):
@abc.abstractmethod
def read(self):
pass
@abc.abstractmethod
def write(self):
pass
#父类使用了抽象类,那子类就必须继承父类的方法,而且名字也必须一样
#这样就实现了代码级别的限制 class Txt(File):
def read(self):
print('文本文档的读取方式')
def write(self):
print('文本文档的写入方式')
4.继承的实现原理
1)继承顺序:
python支持多继承,当一个类继承多个父类时,继承顺序是怎样的呢?这个顺序在新式类和经典类中是不一样的。
在新式类中,继承顺序是广度优先,在经典类中是深度优先,举个栗子:
图不重要,看内容
在这个图中,H是子类,H继承E,F,G,E,F,G,又分别继承B,C,D,B,C,D,同时继承A
在新式类中的顺序是:H E B F C G D A
在经典类中的顺序是:H E B A F C G D
2)继承原理:
当我们定义一个类后,Python就会根据上面的继承规律解析出一个继承顺序的列表(MRO列表),可以通过mro()查看,但是这个方法只有在新式类中才有,经典类没有
3)super()方法
我们之前用继承是怎么用的来着,
class Parent(object):
def __init__(self,name,age):
self.name=name
self.age=age class Child(Parent):
def __init__(self,name,age,salary):
Parent.__init__(self,name,age,salary)
self.salary=salary
这其实是和继承没啥关系的写法,如果父类名字改了,在子类中也要改,更优雅的写法是用super()
class Parent(object):
def __init__(self,name,age):
self.name=name
self.age=age class Child(Parent):
def __init__(self,name,age,salary):
super().__init__(name,age)
self.salary=salary
这是python3中的写法,如果是python2,super后面的括号里要写(Child,self)
注意:super()方法只适用于新式类
如果是多继承的关系,就用到mro列表,如果就是要继承多个父类的方法,那就还是乖乖的用以前指名道姓的方法引用
Python面向对象编程(二)的更多相关文章
- Python进阶之面向对象编程(二)
Python面向对象编程(二) .note-content {font-family: "Helvetica Neue",Arial,"Hiragino Sans GB& ...
- python 面向对象编程(一)
一.如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法. 类是对现实世界中一些事物的封装,定义一个类可以采用下面的方式来定义: class c ...
- python面向对象编程进阶
python面向对象编程进阶 一.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 1 ...
- Python 面向对象编程 继承 和多态
Python 面向对象编程 继承 和多态 一:多继承性 对于java我们熟悉的是一个类只能继承一个父类:但是对于C++ 一个子类可以有多个父亲,同样对于 Python一个类也可以有多个父亲 格式: c ...
- Python 面向对象编程基础
Python 面向对象编程基础 虽然Pthon是解释性语言,但是Pthon可以进行面向对象开发,小到 脚本程序,大到3D游戏,Python都可以做到. 一类: 语法: class 类名: 类属性,方法 ...
- Python面向对象编程——继承与派生
Python面向对象编程--继承与派生 一.初始继承 1.什么是继承 继承指的是类与类之间的关系,是一种什么"是"什么的关系,继承的功能之一就是用来解决代码重用问题. 继承是一种创 ...
- python 面向对象编程学习
1. 问题:将所有代码放入一个py文件:无法维护 方案:如果将代码才分放到多个py文件,好处: 1. 同一个名字的变量互相不影响 2.易于维护 3.引用模块: import module 2.包:解决 ...
- Python面向对象编程指南
Python面向对象编程指南(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1SbD4gum4yGcUruH9icTPCQ 提取码:fzk5 复制这段内容后打开百度网 ...
- Python面向对象编程(下)
本文主要通过几个实例介绍Python面向对象编程中的封装.继承.多态三大特性. 封装性 我们还是继续来看下上文中的例子,使用Student类创建一个对象,并修改对象的属性.代码如下: #-*- cod ...
- Python 面向对象编程——访问限制
<无访问限制的对象> 在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑.但是,从前面Student类的定义来看(见:Py ...
随机推荐
- Idea中执行TestNg报错
今天在Idea中使用TestNg过程中报错: java.lang.AbstractMethodError: org.testng.remote.RemoteTestNG$DelegatingTestR ...
- 【WPF】用三角形网格构建三维图形
虽然WPF只能支持部分三维模型,不过从应用功能开发的角度看,也已经够用了(非游戏开发).WPF 的三维图形,说得简单一点,也就两种而已. 1.把二维对象放到三维空间中,这个应该较为好办,像 Image ...
- javascript的运行过程以及setTimeout的运行机制
关于javascript的运行机制大家都应该有所了解了吧,其实javascript是一个单线程的机制,但是因为队列的关系它的表现会让我们感觉是一个多线程的错觉.javascript在运行的时候是这样的 ...
- 【源码分享】jquery+css实现侧边导航栏
jquery+css实现侧边导航栏 最近做项目的时候,突然想用一个侧边导航栏,网上找了几个插件,有的太丑而且不太符合我的预期.与其修改别人的代码,不如自己来写一个了.废话不多说先上图,感兴趣的请继续看 ...
- integer与int区别以及integer.values()方法详解
声明:本文为博主转载文章,原文地址见文末. 知识点1:integer和int的区别 /* * int是java提供的8种原始数据类型之一.Java为每个原始类型提供了封装类,Integer是java为 ...
- 每天一个JS 小demo之个人信息添加。主要知识点:DOM操作中的表格操作,节点操作
以下是简易效果: <!DOCTYPE html><html lang="en"><head> <meta charset="UT ...
- 懵懂oracle之存储过程2
上篇<懵懂oracle之存储过程>已经给大家介绍了很多关于开发存储过程相关的基础知识,笔者尽最大的努力总结了所有接触到的关于存储过程的知识,分享给大家和大家一起学习进步.本篇文章既是完成上 ...
- Hibernate入门(四)
一 Hibernate缓存 缓存是介于应用程序和数据库之间,对数据库中的数据复制一份到缓存中,其作用就是为了减少应用程序对数据库的访问,访问数据库时先从缓存中取,提高了程序的性能.Hibernate缓 ...
- 用CSS美化checkbox复选按钮和raido单选按钮-适用于移动端
最终效果: 实现方法 index.html: <!DOCTYPE html> <html> <head> <title></title> & ...
- css3实现可以计算的自适应布局——calc()
开始我们需要先了解什么是calc() ,calc()是一个CSS函数,你可以使用calc()给元素的margin.pading.width等属性设置 而且你还可以在一个calc()内部嵌套另一个cal ...