C语言基础学习PYTHON——基础学习D06
20180821内容纲要:
面向对象初级学习
1 面向对象
2 类
(1)封装
(2)继承
(3)多态
3 小结
4 练习:选课系统
5 课外拓展:答题系统
1 面向对象
先说什么是面向过程编程(procedural programm)。
procedural programm uses a list of institutions to tell the computer what to do step by step.
基本设计思路就是程序一开始幺解决一个大问题,然后把一个大问题分解成很多小问题,继续分解直至简单到可以一步解决的问题。
不方便修改和维护,如果需要不断地迭代且各部分之间相互依赖。面向过程可能就没那么简单了。
再说什么是面向对象编程(Object Orientation Programming)
利用类和对象来创建各种模型来实现对真实世界的描述。面向对象更加容易理解代码逻辑。
方便程序的维护和扩展变得简单,并且大大提高程序的考法效率。
其实我觉得面向过程其实就是简单的一次性的脚本,而面向对象是一种经过封装的结构化程序,更加规范。面向对象的主要优势就是对于后续的维护和更新会更加便捷!
所以我们一般认为, 如果你只是写一些简单的脚本,去做一些一次性任务,用面向过程的方式是极好的,但如果你要处理的任务是复杂的,且需要不断迭代和维护 的, 那还是用面向对象最方便了。
说的这么神奇,那就来看看吧~相信大家都打过CS游戏吧,我们就自己开发一个简单版的CS来玩一玩。
暂不考虑开发场地等复杂的东西,我们先从人物角色下手, 角色很简单,就俩个,恐怖份子、警察,他们除了角色不同,其它基本都 一样,每个人都有生命值、武器等。
用OOP的方式写出游戏的基本角色
1 #Author:ZhangKanghui 2 3 class Role: 4 n =123 #类变量 5 n_list =[] 6 name ="嘿嘿" 7 def __init__(self, name, role, weapon, life_value=100, money=10000): 8 #构造函数,在实例化时做类的初始化 9 self.name = name #实例变量(又叫静态属性),作用域就是实例本身 10 self.role = role #相当于r1.role = role 11 self.weapon = weapon 12 self.life_value = life_value 13 self.money = money 14 15 def shoot(self): #类的方法,功能(动态属性) 16 print("shooting") 17 def get_shot(self): 18 print("ah... i got shot") 19 def buy_gun(self,gun_name): 20 print("%s just bought %s" % (self.name, gun_name)) 21 22 23 print(Role.n) 24 #把一个类变成一个具体的对象的过程叫实例化 25 r1 =Role('ersha','police','AK47') #这个过程就是类的实例化 r1就是Role这个类的实例。 26 # 在这里可以改名,即修改属性 27 r1.name ='习大大' 28 #在这里添加一个属性可以吗?当然没问题。即添加属性 29 r1.bullet =True 30 #当然还有删除属性 31 del r1.weapon 32 #print(r1.weapon) 看看是不是删掉了 33 # 有实例变量优先使用实例变量,没有采用类变量。在实例中可以查到类变量。那么能不能修改类变量呢? 34 print(r1.n,r1.name) 35 #来看看能不能‘修改’类变量。r1,r2会有不同吗? 36 r1.n ='修改类变量' #相当于在r1的实例中创建一个实例变量n,并非修改 37 print("r1:", r1.name,r1.n) 38 39 r2 =Role('dasha','terrorist','B22') 40 41 r1.buy_gun('AK47') 42 Role('sansha','police','98K').get_shot() 43 print("r2:", r2.name,r2.n) 44 45 #那么,此时我再修改类变量,再次输出r1.n,r2.n会是什么样呢? 46 Role.n ='ABC' 47 print(r1.n,r2.n) #发现r1.n并没有改变,而r2.n变了。这是因为在r1有了实例变量n,而r2没有。 48 49 #那么。接下来问题再次升级。如果是一个列表。会有什么不一样呢。 50 r1.n_list.append("from r1") 51 r2.n_list.append("from r2") 52 print(r1.n_list,r2.n_list) 53 print(Role.n_list) 54 #这个时候你会发现他们三个共用同一个内存地址。所以无论怎么修改都是一样的。
没看懂?下面分解来看看~
2 类
先来介绍两个概念:
(1)类class:一类具有相同属性的对象的抽象、蓝图、原型。
(2)对象object:一个类的实例化后的实例。一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象。
那什么是类呢?
1 class Dog(object): 2 3 print("hello,I am a dog!") 4 5 6 d = Dog() #实例化这个类, 7 #此时的d就是类Dog的实例化对象 8 9 #实例化,其实就是以Dog类为模版,在内存里开辟一块空间,存上数据,赋值成一个变量名
1 #Author:ZhangKanghui 2 3 class dog: 4 def __init__(self,name): 5 self.name = name 6 7 def bulk(self): 8 print("%s :喵喵喵" %self.name) 9 10 d1 =dog("二炮") 11 d2 =dog("三炮") 12 d3 =dog("老炮") 13 14 d1.bulk() 15 d2.bulk() 16 d3.bulk()
通过类的初识(__inint__(self)是什么鬼?)那先来一个新的名词叫析构函数。
析构函数:在实例释放、销毁的时候执行的,通常做一些扫尾工作,比如关闭一些数据库链接。打开的临时文件。
1 #Author:ZhangKanghui 2 3 class Role: 4 n =123 #类变量 5 n_list =[] 6 name ="嘿嘿" 7 def __init__(self, name, role, weapon, life_value=100, money=10000): 8 #构造函数,在实例化时做类的初始化 9 self.name = name #实例变量(又叫静态属性),作用域就是实例本身 10 self.role = role #相当于r1.role = role 11 self.weapon = weapon 12 self.life_value = life_value 13 self.money = money 14 15 def shoot(self): #类的方法,功能(动态属性) 16 print("shooting") 17 def get_shot(self): 18 print("ah... i got shot") 19 def buy_gun(self,gun_name): 20 print("%s just bought %s" % (self.name, gun_name)) 21 22 def __del__(self): 23 print("%s is Game Over"% self.name) 24 r1 =Role('ersha','police','AK47') 25 #刚实例化生成一个对象还什么都没干就结束了?那先操作一下呢 26 r1.buy_gun("AK47") 27 r1.get_shot() 28 ###### del r1 29 30 #最后还是game over,那再生成一个角色 31 r2 =Role('dasha','terrorist','B22') 32 r2.get_shot() 33 #这个时候发现正产顺序依次执行之后,都会gg 34 #del在实例释放或销毁的时候执行,所以最后执行。 35 #那么如果我在实例释放之前就把他删除会怎么样呢?那就在r1最后添加del r1、看一下执行结果。
这个__init__()叫做初始化方法(或构造方法), 在类被调用时,这个方法(虽然它是函数形式,但在类中就不叫函数了,叫方法)会自动执行,进行一些初始化的动作。
认识了类。那就来看看关于类的一些常识。
a.类变量:大家共有的属性,对于共有属性和默认参数,能够节省内存。节约成本
b.实例变量
c.经典类
d.新式类
e.私有方法
f.私有属性
经典类和新式类对于我们的不同之处就是多继承。
这些都是什么意思呢?直接上代码~看一下
1 #Author:ZhangKanghui 2 3 class Role: 4 n =123 #类变量 5 n_list =[] 6 name ="嘿嘿" 7 def __init__(self, name, role, weapon, life_value=100, money=10000): 8 #构造函数,在实例化时做类的初始化 9 self.name = name #实例变量(又叫静态属性),作用域就是实例本身 10 self.role = role #相当于r1.role = role 11 self.weapon = weapon 12 self.__life_value = life_value 13 self.money = money 14 15 def __shoot(self): # 类的方法,功能(动态属性) 16 print("shooting") 17 18 def get_shot(self): 19 self.__life_value -=50 20 print("ah... i got shot") 21 22 def buy_gun(self, gun_name): 23 print("%s just bought %s" % (self.name, gun_name)) 24 25 26 def show_status(self): 27 print("name:%s weapon :%s life_value:%s "%(self.name,self.weapon,self.__life_value)) 28 #私有属性。如何把生命值设置私有属性呢?两个下划线 29 r1 =Role('ersha','police','AK47') 30 r1.buy_gun("AK47") 31 r1.get_shot() 32 #print(r1.__life_value) 没有这个属性。这个时候完全不能访问了,不能被修改,但是至少能显示血量还剩多少不过分吧 33 #定义一个方法 34 print(r1.show_status()) 35 36 #那么有私有属性。有没有私有方法呢? 37 #r1.__shoot() AttributeError: 'Role' object has no attribute '__shoot'
接下来介绍类的三种特性:
(1)封装Encapsulation:在类中对数据进行赋值,内部调用对外部是透明的。里面包含着类的数据和方法。封装可以隐藏实现的细节,使代码模块化。
(2)继承Inheritance:一个类可以派生出子类。在这个父类里定义的属性、方法自动被子类继承。继承可以扩展代码模块(类)。
(3)多态Polymorphism:一个接口,多种实现。指一个基类中派生出了不同的子类,且每个子类在继承了同样方法名的同时又对父类的方法做了不同的实现。
看过这些代码大概能明白是封装了吧。封装,其实就是使用构造方法将内容封装到某个具体对象中,然后通过对象直接或者self间接获取被封装的内容,不知道那就接着看什么是继承。
1 多态的作用就是在类的继承和派生的同时,保证使用家谱中任一类的实例的某一属性时的正确调用。python中没有直接的语法支持多态但是可以间接实现。
1 #Author:ZhangKanghui 2 3 class A: 4 def __init__(self): 5 print("A") 6 class B(A): 7 pass 8 # def __init__(self): 9 # print("B") 10 class C(A): 11 pass 12 # def __init__(self): 13 # print("C") 14 class D(B,C): 15 pass 16 17 obj =D() #多继承按顺序寻址,先B后C,所以输出B 18 #这个时候把B中的构造函数注释掉。看一下执行结果。一定是C 19 #那么这个时候如果C里面也没有呢?是不是找A呀
多继承是顺序继承,也就是说如果两个父类中有相同属性方法等,按顺序寻址,如果第一个父类有,那第二个就不会执行。
python2经典类是按深度优先继承的;新式类是按广度优先来继承的。python3中经典类和新式类统一按广度优先继承的。
看完这些,那就来个实例小试牛刀吧~
1 #Author:ZhangKanghui 2 3 class School(object): 4 def __init__(self,name,addr): 5 self.name = name 6 self.addr = addr 7 self.students = [] 8 self.staffs = [] 9 def enroll(self,stu_obj): 10 print("welcome %s to shcool" % stu_obj.name) 11 self.students.append(stu_obj) 12 def hire(self,staff_obj): 13 print("welcome %s to shcool" % staff_obj.name) 14 self.staffs.append(staff_obj) 15 16 class SchoolMember(object): 17 def __init__(self,name,age,sex): 18 self.name = name 19 self.age = age 20 self.sex =sex 21 def info(self): 22 pass 23 24 25 class Teacher(SchoolMember): 26 def __init__(self,name,age,sex,salary,course): 27 super(Teacher,self).__init__(name,age,sex) 28 self.salary = salary 29 self.course = course 30 def info(self): 31 print(''' 32 ------info of Teacher:%s------- 33 Name:%s 34 Age:%s 35 sex:%s 36 salary:%s 37 course:%s 38 '''%(self.name,self.name,self.age,self.sex,self.salary,self.course)) 39 def teach(self): 40 print("%s is teaching course [%s]"%(self.name,self.course)) 41 42 class Student(SchoolMember): 43 def __init__(self,name,age,sex,stu_id,grade): 44 super(Student,self).__init__(name,age,sex) 45 self.stu_id = stu_id 46 self.grade = grade 47 def info(self): 48 print(''' 49 ------info of Student:%s------- 50 Name:%s 51 Age:%s 52 sex:%s 53 stu_id:%s 54 grade:%s 55 '''%(self.name,self.name,self.age,self.sex,self.stu_id,self.grade)) 56 def pay_fee(self,amount): 57 print("%s had paid fee for $[%s]"%(self.name,amount)) 58 59 school = School("清北","北平") 60 61 t1 =Teacher("Sol",30,"Boy",10000,"English") 62 t2 =Teacher("Crystal_Lan",30,"Girl",10000,"English") 63 s1 =Student("Kanghui",20,"Boy",'001',"Python") 64 s2 =Student("Ruixin",30,"Boy",'002',"Yixue") 65 66 t1.info() 67 s1.info() 68 69 school.hire(t1) 70 school.enroll(s1) 71 school.enroll(s2) 72 print(school.students) 73 print(school.staffs) 74 school.staffs[0].teach() 75 76 for stu in school.students: 77 stu.pay_fee(5000)
最后看看什么是多态,其实python中没有直接的语法支持多态,但是可以通过间接的方式实现。
多态的作用就是在类的继承和派生的同时,保证使用家谱中任一类的实例的某一属性时的正确调用。python中没有直接的语法支持多态但是可以间接实现。
1 #Author:ZhangKanghui 2 3 class Animal(object): 4 def __init__(self,name): 5 self.name = name 6 7 def bark(self): 8 pass 9 @staticmethod 10 def animal_bark(obj): 11 obj.bark() 12 13 class Cat(Animal): 14 def bark(self): 15 print("miao miao miao") 16 17 class Dog(Animal): 18 def bark(self): 19 print("wang wang wang") 20 21 c =Cat("小狗") 22 d =Dog("小猫") 23 # c.bark() 24 # d.bark() 25 #这样虽然实现了各功能,但是每种动物叫的调用都不同,能不能用同一种调用方式呢?那先把上面注释掉 26 #试试这样 27 28 # def animal_bark(obj): 29 # obj.bark() 30 # 31 # animal_bark(c) 32 # animal_bark(d) 33 #现在好像就可以实现一种接口多种实现了。那么我们把他放进父类里。把上面注释掉 34 #在父类里添加 35 36 Animal.animal_bark(c) 37 Animal.animal_bark(d) 38 #这样就能实现一种接口多种实现了.这就是多态.这就实现了接口的重用.
3 小结
面向对象设计的由来:http://www.cnblogs.com/linhaifeng/articles/6428835.html
这个内容有点多,有点懵逼。可我总觉得有一天我都会。不知道哪来的自信。大概是梁静茹给的勇气吧~!!!
主要还是练得少。多看多写多思考!!!多动手~!!!
4 练习
角色:学校、学员、课程、讲师
要求:
1. 创建北京、上海 2 所学校
2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开
3. 课程包含,周期,价格,通过学校创建课程
4. 通过学校创建班级, 班级关联课程、讲师
5. 创建学员时,选择学校,关联班级
5. 创建讲师角色时要关联学校,
6. 提供两个角色接口
6.1 学员视图, 可以注册, 交学费, 选择班级,
6.2 讲师视图, 讲师可管理自己的班级, 上课时选择班级, 查看班级学员列表 , 修改所管理的学员的成绩
6.3 管理视图,创建讲师, 创建班级,创建课程
7. 上面的操作产生的数据都通过pickle序列化保存到文件里
第一步:选课系统用例
1 #用例名称 2 选课 3 #场景 4 who:学生,老师,管理员 5 where:老男孩 6 when:任意时间 7 8 #用例描述(用户怎么做,或者说用户想怎么用): 9 1. 管理员创建学校:北京和上海两个校区 10 2. 管理员创建课程:python,go,linux 11 3. 管理员创建班级:python周末18期,python脱产7期,linux架构35期 12 4. 管理员创建学员:小晴,花野真衣,川岛芳子 13 5. 管理员创建讲师:alex,egon,wupeiqi,yuanhao 14 6. 讲师创建上课记录:python周末班18期day7 15 7. 讲师为day7这节课所有学生批改作业,为每个学生打分 16 8. 学员杨磊查看自己的详细信息:所在学校,报名课程,所在班级 17 9. 学员杨磊在python18期day7提交了作业 18 10.学员杨磊查看了自己在day7作业的成绩列表,然后自杀了 19 11.学员小晴跟egon表白了,当天下午就去领了结婚证 20 21 #用例价值 22 23 帮老男孩解决课程管理问题 24 #约束
第二步:找名词
1 管理员,学校,课程,班级,学员讲师,上课记录,作业,分数,学员详细信息,成绩列表,结婚证 2 筛选:去掉与行业或者说领域无关的名词 3 管理员,学校,课程,班级,学员,讲师,上课记录,作业,分数,学员详细信息,成绩列表
第三步:加属性
1 名字 属性 备注 2 管理员 NA 具备所有权限,对于选课系统来说,并不需要管理员的属性,因此在领域模型中,管理员是没有属性的 3 学校 学校名,地址,课程列表,班级列表 4 课程 课程名,周期,价钱,大纲 5 班级 班级名,所属学校,课程 6 学员 学员名, 7 讲师 讲师名 8 上课记录 班级,课程节次,日期
第四步:连关系
第五步:写代码
https://www.cnblogs.com/lianzhilei/p/5832691.html
http://www.cnblogs.com/lianzhilei/p/5985333.html
说好的以后要看?我真的会看嘛?
5 课外拓展:答题系统案例
第一步:需求分析(写用例)
1 #用例名 2 答题系统 3 4 #场景: 5 when:8.10开始 6 where:老男孩 7 who:linux学院,网络客户 8 9 #用例描述: 10 1 linux学院提供50道题 11 2 每个客户无需输入任何个人信息就可以参与答题,随机选择20道题,给客户回答,每道题5分, 12 3.答题结束后,输入手机号,提交,算总分 13 4 60分参与抽奖,<60分赠送基础视频 14 15 16 #用户价值: 17 答题有奖,答题提交时输入自己的手机号获取成绩,获得潜在客户的联系方式,为后期将客户转成学员做准备 18 19 #约束: 20 暂无
第二步:领域模型(找名词,加属性,连关系=>出图)
1 #找名词: 2 linux学院,题,客户,得分,奖,视频 3 #筛选:去掉与领域无关的名词。视频应该算作一种奖品 4 linux学院,题,客户,得分,奖
1 #加属性 2 加属性 3 名词 属性 备注 4 linux学院 NA 对于答题系统来说,并不需要linux学院的属性,因此在领域模型中,linux学院是没有属性的 5 题 题目编号,题目类型,题目描述,答题选项,正确答案,分数 6 客户 客户编号,姓名,性别,年龄,手机号 7 答题记录 记录编号,客户编号,题目编号列表,总分数,时间 通过答题记录就可以知道用户是谁,以及用户答过的题目 8 奖品 奖品编号,奖品名字
1 #连关系:画图 2 1:答题记录是客户与题的关系类,而客户与奖品之间可以建一个关系类,这样以后单查关系类就可以知道谁得了什么奖品 3 2:找动词: 4 创建题目 5 随机选择题目 6 答题 7 提交 8 算总分 9 抽奖
最后看代码:
链接:https://pan.baidu.com/s/1qyy7Gdsziwfcy_C8OFrAFg 密码:rrjf
还有个面向对象的小练习,有兴趣可以点进来看看~基于面向对象设计一个对战小游戏~!!!
http://www.cnblogs.com/linhaifeng/articles/7340497.html
我是尾巴~
推荐一些小工具,彻底解放电脑桌面: