总结
为什么要用面向对象:
函数仍然无法高度的组织程序,这时候就要用面向对象
什么时候用函数,什么时候用面向对象:
当一个函数需要操作专门的数据的时候,应该封装成一个类,把数据和功能捆绑到一起
如何用面向对象:
把对象相似的东西存到类这个容器里,把对象不同的东西存到对象自己这
类的使用:
1、定义类
2、引用类的属性
3、调用类产生对象,即实例化
对象的使用:
1、引用对象属性
2、属性查找:对象---对象的类---父类
3、绑定方法的自动传值
一、对象
指的是特征与技能的结合体
面向对象编程的优点:可扩展性强
缺点:编程的复杂度高于面向过程
二、类
类是一系列对象相同的特征与技能的结合体
在程序中,必须先定义类,再调用类来产生对象,定义类的目的是为了调用类来产生对象,对象是变量+函数
定义类的语法:
class 类名: 类名用驼峰体,首字母大写
用变量表示特征,用函数表示技能
类中最常见的就是输出变量与函数的定义,但类中是可以有任意python代码的
定义函数与定义类的区别:
1、定义函数只检测语法不执行函数体代码
2、定义类会立刻执行类体代码,会产生类的名称空间,将类体代码执行过程中产生的名字都存放到类的名称空间中
3、存的目的是为了取,要想从类的名称空间中取出我们定义的名字
在定义阶段,会立刻执行类体内的代码,然后将【产生的名字】存放于类名称空间中。使用类名.__dict__查看名称空间
使用类用 . ,和模块类似,. 的前面是名称空间,. 后的叫【属性】
三、类的对象
对象由连同调用类时括号内的参数组成
类对象支持两种操作:属性引用和实例化
四、类的方法
在类内部,使用def关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数self,且为第一个参数。self代表的时类的实例,而非类
五、__init__方法
在类内定义一个__init__函数,该函数会在调用类时自动触发执行
作用:用来在类调用阶段,为类初始化独有属性
1、该方法内可以有任意python代码
2、一定不能有返回值
六、调用类——类的实例化
调用类用(),【产生类的对象】,该对象也可以称为类的一个实例,调用类的过程也称为类的实例化
调用类(实例化)的时候发生了:
1、首先会产生一个空对象
2、会自动触发类内部的__init__函数
3、然后将空对象,以及调用类括号内传入的参数一同传给__init__函数,为对象定制独有的属性
在类内部但凡定义一个函数,都会自动传入一个self参数,对象来调的时候,会自动把自己传进来
self在定义时需要定义,但是在调用时会自动传入
self的名字并不是规定死的,但是最好还是按照约定是用self
self总是指调用时的类的实例
七、对象操作
用类名.__dict__ 查看名称空间
类名.属性 查看
类名.属性 = 增加的内容 增加
类名.属性 = 修改的内容 修改
del 类名.属性 删除
八、对象属性的查找顺序
先找对象自己的名称空间——再查找类的名称空间
类的数据属性,是给对象用的,而且是直接共享给所有对象用的,内存地址都一样
类的函数属性,也是给对象用的,但是给绑定对象用的,绑定到不同的对象就是不同的绑定方法,内存地址都不一样,但其实只是都是同一个功能
九、绑定方法
绑定方法的意思是类的函数属性是绑定给对象使用
绑定方法的特殊之处在于:绑定给谁,就应该由谁来调用;谁来调用,就会将谁当作第一个参数自动传入
类内部定义的函数,类可以使用,但类来用的时候就是一个普通函数,普通函数有几个参数就传入几个参数
类内部定义的函数,其实是给对象使用的,而且是绑定给对象使用的,绑定给不同的对象就是不同的绑定方法
类内部定义的变量是给所有对象共享的,所有对象指向的都是同一个内存地址
十、一切皆对象
类与类型是一个概念
十一、继承
继承是一种新建类的方式,新建的类称为子类或派生类,父类又可以基类或超类
在python中支持一个子类可以继承多个父类,子类会遗传父类的属性
继承的好处:减少代码冗余
在python3中,如果一个类没有指定继承的父类,默认就继承object
在菱形继承的背景下,查找属性:
经典类:深度优先
新式类:广度优先
寻找继承关系:继承是类与类之间的关系,寻找这中关系需要先抽象再继承
十二、派生
子类定义自己新的属性,如果与父类同名,以子类自己的为准
十三、在子类派生出的新方法重用父类的功能,也叫方法重写
方式一:指名道姓的调用(其实与继承没有关系),需要把self传进去
方式二:super()调用(严格依赖于继承)
super()的返回值是一个特殊的对象,该对象专门用来调用父类中的属性,不需要传self
super().__init__()
十四、组合
解决类于类之间代码冗余问题有两种解决方法:1、继承 2、组合
和继承相比,组合的解耦和更高,所以能用组合就用组合
继承描述的是类与类之间什么是什么的关系
组合描述的是类与类之间的关系,是一种什么有什么的关系
十五、封装
封装就是把一堆属性存起来,然后把这个属性隐藏起来
封装的目的:为了隔离复杂度。明确的区分内外,对外是隐藏的,对内是开放的。把数据属性封装起来,然后需要开辟接口给类使用,好处是可以在接口之上添加控制逻辑,从而严格控制访问者对属性的操作
在属性前面加__开头就可以把属性隐藏起来(注意不要加__结尾)
注意点:
1、其实这种隐藏只是一种语法上的变形,对外不对内
2、这种语法意义上的变形,只在类定义阶段发生一次,类定义之后,新增的_开头的属性都没有变形的效果
3、如果父类不想让子类覆盖自己的方法,可以在方法名前加__开头
发生了:
在类定义阶段将属性名统一变形:_自己的类名__属性名
property模块
用来将类内的函数伪装成一个数据属性
十六、多态
多态指的是同一种事物有多种形态,在程序中用继承来表示从属关系
多态性:可以在不用考虑对象具体类型的前提下而之间使用对象下的方法
abc模块
十七、绑定方法与非绑定方法
@classmethod:绑定方法,将类中的一个函数绑定给类
@staticmethod:非绑定方法,将类中的一个函数解除绑定
十八、反射
通过字符串来操作类与对象的属性,这种操作称为反射
内置函数
isinstance() 判断一个对象的类型
issubclass() 判断一个类是不是类一个类的子类
专门用来操作类与对象属性的函数
hasattr() 判断
getattr() 获取
setattr() 设置
delattr() 删除
十九、类内置的专有方法
__init__ 构造函数,在生成对象时调用
__del__ 析构函数,释放对象时使用,对象被删除的条件下,自动执行
__repr__ 打印,转换
__setitem__ 按照索引赋值
__getitem__ 按照索引获取值
__len__ 获取长度
__cmp__ 比较运算
__call__ 函数调用
__add__ 加运算
__sub__ 减运算
__mul__ 乘运算
__div__ 除运算
__mod__ 求余运算
__pow__ 乘方
__class__ 用于获取当前的实例对象时哪个类
__name__ 1)当文件是被调用时,__name__的值为模块名;2)当文件被执行时,__name__的值为'__main__'
二十、元类
exec() 用来处理字符串里的代码
类的类就是元类
用class定义的类使用来产生我们自己的对象的
内置元类type是用来专门产生class定义的类
用内置的元类type(),来实例化得到我们的类
type(类名,类的基类,类的字典)
自定义元类:1、来控制来的创建 2、控制类的调用过程(实例化的过程)
二十一、单例模式
单例指的是一个类的实例从始至终只能被创建一次。单例模式的主要目的是确保某一个类只有一个实例存在
实现单例模式的方法:
1、使用__new__方法
2、使用装饰器
3、使用元类
4、使用模块:python的模块就是天然的单例模式,只需把相关的函数和数据定义在一个模块中,就可以得到一个单例对象