九:面向对象
1.OOP
python没有面向对象完全可以用函数解决所有的编程问题,有了OOP让变成更加有条理.
函数内部的的数据可以视为类属性,函数外部的数据视为实例属性,因此没有函数完全可以完成变成,就像闭包,装饰器那样。有了OOP变成更加人性化,简单化而已。
但是java就是完全的面向对象,所有都封装在类里面,单独方法不能出现在类之外,类中不能有语句。
而python就很灵活,类里面可以有语句,可以做但并不意味着就去做,往往那样做只会造成代码逻辑混乱。
面相函数编程:多数情况下数据是函数内部传入函数内部,得到函数执行结果,完成需求,但是调用完函数就会从内存消失,为了解决此问题出现了闭包,但是闭包的扩展性(例如闭包里面只有内部函数封装了已一小段逻辑,而类中可以封装多个不同的逻辑于不同的方法中),因此出现了OOP。
面向对象编程:将数据初始化的时候封装到对象里面,方法用数据直接用对象里面的,这样外界拿到对象引用就可以调用里面除了私有之外的一切了,操作性很强,也很易于理解,因此推广了起来。
面向函数数据和逻辑是分离的,面向对象的数据和函数是封装在一个对象里面常驻内存,方便后续重复使用.
从IDE角度来讲,面向函数编程那么多函数名根本记不住,那么面向对象把解决一类问题的方法放到一个类中,创建对象初始化传入数据,拿着这个对象就可以解决此类问题,对象.方法名,不用记住因为有提示.
1.1面向对象VS面向函数
面向函数定义简单,调用简单,面向函数里面的*args和**kwargs其实就是封装的意思,但是传的数据是随意的个数,访问只能用索引
oop中通过初始化方法,将数据封装到对象里面,用的时候直接self.属性名就可以拿值,没有的属性名.不出来,也获取不到值,对数据进行了范围约束.
面向对象定义复杂,调用复杂,但是它将解决一类问题的方法进行了分类,逻辑上结构上更清晰,更加符合人类的思维.
函数是编程如果没有默认参数,每次调用都要开栈帧,传数据.
面向对象,用类创建对象一次将数据传入,方法里面直接调用数据,调用的时候不用传参了,oop通过构造方法将数据封装到对象中.
性能方面:例如一个函数专门负责打开一个文件,所有的方法的第一步都是打开文件,调用完就结束了,磁盘IO很费性能,打开一次通道之后最好不关,一直使用直到不用,而不是用到就打开,不用就关上
而OOP在初始化的时候就放了一个f=open()打开了一个文件,那么这个对象始终持有此文件句柄,如果是网络传输打开文件,那就更费性能了,程序阻塞在那一直等待连接服务器,然后打开文件.
1.2归类
函数编程不能归类,没有学OOp之前用模块即py文件将相同功能的归于一类放在一个py文件中
java中一个文件就是一个类文件里面放处理这类问题的数据和功能,都放在一个类中
python中更加灵活,py文件中可以有函数,可以有类,也可以像java一样将函数封装到类里面,尽管个类没有任何关系,也和类里面的数据没有任何关系,就封装为@staticmethod
1.3OOP步骤
- 归类+提取公共值,这是反推
- 写之前已经构思好了,直接在类中编写类相关的所有代码.
说了那么多的理论其实对于编码没有任何影响,编码你只要会创建对象,调用方法即可,但是上面的起因结果可以帮我们更好的理解软件工程。
2.三大特性
2.1封装
属性私有化,对外暴露处理数据的接口,更加安全的限制数据,例如传入的年龄是负数,就抛出异常。
私有数据只是用别名的方式来约束,没有做到真正的私有。
2.2继承(为了"偷懒"重用)
- 默认继承object类,
- 遵循__mro__的查找规则来进行继承,
- 个性支持多继承,可以有多个爹,还是遵守__mro__(),更复杂的多继承
- 私有数据无法继承
- 现在自己类中找,没有就找父类,直到object中,还没有就报错
- 菱形 钻石继承
- super()拿到的是父类的引用,严格最受mro规则。