面向对象
面向对象
1.面向过程编程,面向对象编程都是需要熟练掌握的两种编程范式.
-
面向过程,指的是解决问题的步骤,设计一条流水线,机械式的思维方式
-
优点:复杂的问题流程化,进而简单化
-
缺点:可扩展性差
-
应用:举个典型的面向过程的例子, 写一个数据远程备份程序, 分三步,本地数据打包,上传至云服务器,测试备份文件可用性。
自动部署脚本,监控脚本等。。。
-
-
面向对象,核心是对象,对象就是特征(独有属性,变量)与技能(方法,动作,函数)的结合体.
- 优点:可扩展性强.(可扩展性仅仅是软件代码质量高低的一个标准,但是占得比例比较大,所以很重要。)
- 缺点:编程复杂度高
- 应用:用户需求经常变化,例如互联网应用,游戏,企业内部应用
-
面向对象三大特性:
-
Encapsulation 封装
在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法
-
Inheritance 继承
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
-
Polymorphism 多态
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。
对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定
-
为什么要使用面向对象编程?
- 使程序更加容易扩展和易更改,使开发效率变的更高
- 基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
2. 类 class
-
类的概念:
- 类就是一系列对象相似的特征(共有的特征,变量属性)与技能(都具有的技能,函数属性)的结合体
- 在现实世界中,是先有对象,后有类
- 在程序中:得先定义类,然后才能通过类创建对象
- 类中的函数属性:是绑定给对象使用的,绑定到不同的对象是不同的绑定方法,对象调用绑定方法时,会把对象本身当做第一个参数传入,传给self
-
类的语法:
-
class Person(object): def __init__(self, name, age): self.name = name self.age = age p = Person("Alex", 22) print(p.name, p.age)
-
其中self就是实例(对象)本身.在实例化时python解释器会自动把这个实例本身通过self参数传进去
-
构造方法
__init__(...)
被称为 构造方法或初始化方法,在类实例化过程中自动执行,目的是初始化实例的一些属性。每个实例通过__init__初始化的属性都是独有的- 含有_init_()的这个类体现了面向对象的第一个基本特性,封装,其实就是使用构造方法将内容封装到某个具体对象中,然后通过对象直接或者self间接获取被封装的内容
-
在程序中,务必保证:先定义(类),后使用类(用来产生对象)
注意:
- 类中可以有任意python代码,这些代码在类定义阶段便会执行,因而会产生新的名称空间,用来存放类的变量名与函数名,可以通过OldboyStudent.__dict__查看
- 类中定义的名字,都是类的属性,点是访问属性的语法。
- 对于经典类来说我们可以通过该字典操作类名称空间的名字,但新式类有限制
-
3.类的使用
类在定义阶段,内部的代码就会运行
- 数据属性(类内部声明的变量)
- 函数属性(类内部声明的函数,方法)
代码:
- 引用类的属性
OldboyStudent.school #查
OldboyStudent.school='Oldboy' #改
OldboyStudent.x=1 #增
del OldboyStudent.x #删
- 调用类,或称为实例化,得到程序中的对象
s1=OldboyStudent()
s2=OldboyStudent()
s3=OldboyStudent()
#如此,s1、s2、s3都一样了,而这三者除了相似的属性之外还各种不同的属性,这就用到了__init__
- __init__方法
#注意:该方法是在对象产生之后才会执行,只用来为对象进行初始化操作,可以有任意代码,但一定不能有返回值
class OldboyStudent:
......
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
......
s1=OldboyStudent('李坦克','男',18) #先调用类产生空对象s1,然后调用OldboyStudent.__init__(s1,'李坦克','男',18)
s2=OldboyStudent('王大炮','女',38)
s3=OldboyStudent('牛榴弹','男',78)
4.对象的使用
- 加上__init__方法后,实例化的步骤
- 先产生一个空对象
- 类名._init_(空对象名,name, age, sex)
- 上面等同于 对象名 = 类名(name, age, sex)
#执行__init__,s1.name='牛榴弹',很明显也会产生对象的名称空间可以用s2.__dict__查看,查看结果为
{'name': '王大炮', 'age': '女', 'sex': 38}
s2.name #查,等同于s2.__dict__['name']
s2.name='王三炮' #改,等同于s2.__dict__['name']='王三炮'
s2.course='python' #增,等同于s2.__dict__['course']='python'
del s2.course #删,等同于s2.__dict__.pop('course')
补充:
- 站的角度不同,定义出的类是截然不同的;
- 现实中的类并不完全等于程序中的类,比如现实中的公司类,在程序中有时需要拆分成部门类,业务类等;
- 有时为了编程需求,程序中也可能会定义现实中不存在的类,比如策略类,现实中并不存在,但是在程序中却是一个很常见的类。
5.属性查找
- 类的数据属性是所有对象共享的,ID都一样
- 类的函数数据是绑定给对象用的,称为绑定到对象的方法,ID都不一样
- bound method 方法
- 在对象调用数据属性时会先从自己的名称空间(_init_())里找该数据属性,找不到则去类中找,类里面找不到就去父类去找....最后都找不到就抛出异常.
6.绑定方法
-
类中的函数属性:是绑定给对象使用的,绑定到不同的对象是不同的绑定方法,对象调用绑定方法时会把对象本身self当作第一个参数传入,传给self
-
类中定义的函数(没有被任何装饰器装饰的)是类的函数属性,类可以使用,但必须遵循函数的参数规则,有几个参数需要传几个参数
类中定义的函数(没有被任何装饰器装饰的),其实主要是给对象使用的,而且是绑定到对象的,虽然所有对象指向的都是相同的功能,但是绑定到不同的对象就是不同的绑定方法
强调:绑定到对象的方法的特殊之处在于,绑定给谁就由谁来调用,谁来调用,就会将‘谁’本身当做第一个参数传给方法,即自动传值(方法__init__也是一样的道理)
注意:绑定到对象的方法的这种自动传值的特征,决定了在类中定义的函数都要默认写一个参数self,self可以是任意名字,但是约定俗成地写出self。
7.python中一切皆对象(类即类型)
python中一切皆为对象,且python3中类与类型是一个概念,类型就是类
#类型dict就是类dict
>>> list
<class 'list'>
#实例化的到3个对象l1,l2,l3
>>> l1=list()
>>> l2=list()
>>> l3=list()
#三个对象都有绑定方法append,是相同的功能,但内存地址不同
>>> l1.append
<built-in method append of list object at 0x10b482b48>
>>> l2.append
<built-in method append of list object at 0x10b482b88>
>>> l3.append
<built-in method append of list object at 0x10b482bc8>
#操作绑定方法l1.append(3),就是在往l1添加3,绝对不会将3添加到l2或l3
>>> l1.append(3)
>>> l1
[3]
>>> l2
[]
>>> l3
[]
#调用类list.append(l3,111)等同于l3.append(111)
>>> list.append(l3,111) #l3.append(111)
>>> l3
[111]
8.总结
使用类:
- 将数据与专门操作该数据的功能整合到一起
- 可扩展性高,如果新增一个类属性,将会立刻反映给所有对象,而对象却无需修改
练习1:编写一个学生类,产生一堆学生对象, (5分钟)
要求:
- 有一个计数器(属性),统计总共实例了多少个对象
练习2:模仿王者荣耀定义两个英雄类, (10分钟)
要求:
- 英雄需要有昵称、攻击力、生命值等属性;
- 实例化出两个英雄对象;
- 英雄之间可以互殴,被殴打的一方掉血,血量小于0则判定为死亡。