面向对象
主要内容:
一、面向对象介绍
二、类、实例、属性、方法详解
三、练习题
四、综合作业
1️⃣ 面向对象介绍
1、编程范式
编程是 程序 员 用特定的语法+数据结构+算法 组成的代码来告诉计算机如何执行任务的过程 。
一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方式有很多种不同的方式, 对这些不同的编程方式的特点进行归纳总结得出来的编程方式类别,即为编程范式。 不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路, 大多数语言只支持一种编程范式,当然也有些语言可以同时支持多种编程范式。
两种最重要的编程范式分别是面向过程编程和面向对象编程。
2、面向过程编程(Procedural Programming)
Procedural programming uses a list of instructions to tell the computer what to do step-by-step.
面向过程编程依赖 - 你猜到了- procedures,一个procedure包含一组要被进行计算的步骤, 面向过程又被称为top-down languages, 就是程序从上到下一步步执行,一步步从上到下,从头到尾的解决问题 。基本设计思路就是程序一开始是要着手解决一个大的问题,然后把一个大问题分解成很多个小问题或子过程,这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤范围内解决。
举个典型的面向过程的例子, 写一个数据远程备份程序, 分三步,本地数据打包,上传至云服务器,测试备份文件可用性。示例如下:
def cloud_upload(file):
print("\nconnecting cloud storage center...")
print("cloud storage connected.")
print("upload file...xxx..to cloud...", file)
print('close connection.....')
def data_backup(folder):
print("找到要备份的目录...", folder)
print("将备份文件打包,移至相应目录...")
return '/tmp/backup20181103.zip'
def data_backup_test():
print("\n从另外一台机器将备份文件从远程cloud center下载,看文件是否无损")
def main():
zip_file = data_backup("c:\\users\\alex\欧美100G高清无码")
cloud_upload(zip_file)
data_backup_test()
if __name__ == '__main__':
main()
缺点:这个变量,那这个子过程你也要修改,假如又有一个其它子程序依赖这个子过程 , 那就会发生一连串的影响,随着程序越来越大, 这种编程方式的维护难度会越来越高。
test = 1
def cloud_upload(file):
if test == 1:
print("\nconnecting cloud storage center...")
print("cloud storage connected.")
print("upload file...xxx..to cloud...", file)
print('close connection.....')
return True
else:
print("不备份")
return False
def data_backup(folder):
print("找到要备份的目录...", folder)
print("将备份文件打包,移至相应目录...")
return '/tmp/backup20181103.zip'
def data_backup_test(upload_res):
if upload_res == 1:
print("\n从另外一台机器将备份文件从远程cloud center下载,看文件是否无损")
else:
print("upload error,不备份")
def main():
zip_file = data_backup("c:\\users\\alex\欧美100G高清无码")
res = cloud_upload(zip_file)
data_backup_test(res)
if __name__ == '__main__':
main()
面向过程的一般应用场景:写一些简单的脚本,去做一些一次性任务,用面向过程的方式是极好的,但如果你要处理的任务是复杂的,且需要不断迭代和维护 的, 那还是用面向对象最方便了。
3、面向对象编程(Object Oriented Programing)
OOP(Object Oriented Programing)编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述。
面向过程和面向对象编程的区别:
面向过程 = 个人视角
我要找一家餐馆吃饭,我只需要考虑,我有多少钱,去哪一家店,怎么去,选什么菜就好了,你的每一步都要通过程序写出来,写死了,在这个程序里,你只设定了去吃饭的功能,你说你中途想去拜访一个朋友,那可能导致整个程序的逻辑都要更改。用面向过程的方式写代码,那你关心的就是整个事情的执行过程。
面向对象 = 上帝视角
如果你是上帝,你现在要创世纪,把这么多人、动物、山河造出来,上帝光靠自己干,一个一个的造人,多累呀,让你干这个活,你肯定是先造模子,一个男人模子,一个女人模子,剩下的就一个个复制就行啦。这个模子的作用是什么?模子定义了人这个物种所具备的所有特征\(或者说,我们把具备这些特征的个体归为人类\)。
这个世界上所有的东西都是你定义的,你需要用最高效的方式去造世界,最高效的方式就是,先把世界按物种、样貌、有无生命等各种维度分类,然后给每类东西建模型,再让其在不脱离你基本横型定义的框架下,自我繁衍(世界要多姿多彩,所以即使是同一物种,也要有些不一样)
4、为何要用面向对象?
#1、使程序更加容易扩展和易更改,使开发效率变得更高。
#2、基于面向对象的程序可以使他人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
5、面向对象三大特性
Encapsulation 封装
在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法
Inheritance 继承
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
Polymorphism 多态
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。
对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定
2️⃣ 类、实例、属性、方法详解
1、名词解释
类:一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型、模板。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法
属性:人类包含很多特征,把这些特征用程序来描述的话,叫做属性,比如年龄、身高、性别、姓名等都叫做属性,一个类中,可以有多个属性
方法:人类不止有身高、年龄、性别这些属性,还能做好多事情,比如说话、走路、吃饭等,相比较于属性是名词,说话、走路是动词,这些动词用程序来描述就叫做方法。
实例(对象):一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同
实例化:把一个类转变为一个对象的过程就叫实例化
2、类的方法
构造方法
__init__(...)被称为 构造方法或初始化方法,在例实例化过程中自动执行,目的是初始化实例的一些属性。每个实例通过__init__初始化的属性都是独有的
刚才定义的这个类体现了面向对象的第一个基本特性,封装,其实就是使用构造方法将内容封装到某个具体对象中,然后通过对象直接或者self间接获取被封装的内容
普通方法
定义类的一些正常功能,比如人这个类, 可以说话、走路、吃饭等,每个方法其实想当于一个功能或动作
析构方法(解构方法)
实例在内存中被删除时,会自动执行这个方法,如你在内存里生成了一个人的实例,现在他被打死了,那这个人除了自己的实例要被删除外,可能它在实例外产生的一些痕迹也要清除掉,清除的动作就可以写在这个方法里
综合实例:
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def talk(self):
print("Hello, my name is %s, I'm %s years old!" % (self.name, self.age))
def __del__(self):
print("running del method, this person must be died.")
p = Person("Alex", 22)
p.talk()
del p
print('--end program--')
3️⃣ 练习题
1、面向对象三大特性,各有什么用处,说说你的理解。
2、类的属性和对象的属性有什么区别?
3、面向过程编程与面向对象编程的区别与应用场景?
4、类和对象在内存中是如何保存的。
5、什么是绑定到对象的方法、绑定到类的方法、解除绑定的函数、如何定义,如何调用,给谁用?有什么特性
6、使用实例进行 获取、设置、删除 数据, 分别会触发类的什么私有方法
class A(object):
pass
a = A()
a["key"] = "val"
a = a["key"]
del a["key"]
7、python中经典类和新式类的区别
8、如下示例, 请用面向对象的形式优化以下代码
def exc1(host,port,db,charset,sql):
conn=connect(host,port,db,charset)
conn.execute(sql)
return xxx
def exc2(host,port,db,charset,proc_name)
conn=connect(host,port,db,charset)
conn.call_proc(sql)
return xxx
# 每次调用都需要重复传入一堆参数
exc1('127.0.0.1',3306,'db1','utf8','select * from tb1;')
exc2('127.0.0.1',3306,'db1','utf8','存储过程的名字')
9、示例1, 现有如下代码, 会输出什么:
class People(object):
__name = "luffy"
__age = 18
p1 = People()
print(p1.__name, p1.__age)
10、示例2, 现有如下代码, 会输出什么:
class People(object):
def __init__(self):
print("__init__")
def __new__(cls, *args, **kwargs):
print("__new__")
return object.__new__(cls, *args, **kwargs)
People()
11、请简单解释Python中 staticmethod(静态方法)和 classmethod(类方法), 并分别补充代码执行下列方法。
class A(object):
def foo(self, x):
print("executing foo(%s, %s)" % (self,x))
@classmethod
def class_foo(cls, x):
print("executing class_foo(%s, %s)" % (cls,x))
@staticmethod
def static_foo(x):
print("executing static_foo(%s)" % (x))
a = A()
12、请执行以下代码,解释错误原因,并修正错误。
class Dog(object):
def __init__(self,name):
self.name = name
@property
def eat(self):
print(" %s is eating" %self.name)
d = Dog("ChenRonghua")
d.eat()
13、下面这段代码的输出结果将是什么?请解释。
class Parent(object):
x = 1
class Child1(Parent):
pass
class Child2(Parent):
pass
print(Parent.x, Child1.x, Child2.x)
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
Parent.x = 3
print(Parent.x, Child1.x, Child2.x)
# 1 1 1 继承自父类的类属性x,所以都一样,指向同一块内存地址
# 1 2 1 更改Child1,Child1的x指向了新的内存地址
# 3 2 3 更改Parent,Parent的x指向了新的内存地址
14、多重继承的执行顺序,请解答以下输出结果是什么?并解释。
class A(object):
def __init__(self):
print('A')
super(A, self).__init__()
class B(object):
def __init__(self):
print('B')
super(B, self).__init__()
class C(A):
def __init__(self):
print('C')
super(C, self).__init__()
class D(A):
def __init__(self):
print('D')
super(D, self).__init__()
class E(B, C):
def __init__(self):
print('E')
super(E, self).__init__()
class F(C, B, D):
def __init__(self):
print('F')
super(F, self).__init__()
class G(D, B):
def __init__(self):
print('G')
super(G, self).__init__()
if __name__ == '__main__':
g = G()
f = F()
15、请编写一段符合多态特性的代码.
16、很多同学都是学会了面向对象的语法,却依然写不出面向对象的程序,原因是什么呢?原因就是因为你还没掌握一门面向对象设计利器,即领域建模,请解释下什么是领域建模,以及如何通过其设计面向对象的程序?参考http://www.cnblogs.com/alex3714/articles/5188179.html 此blog最后面有详解
17、请写一个小游戏,人狗大站,2个角色,人和狗,游戏开始后,生成2个人,3条狗,互相混战,人被狗咬了会掉血,狗被人打了也掉血,狗和人的攻击力,具备的功能都不一样。注意,请按题14领域建模的方式来设计类。
18、编写程序, 在元类中控制把自定义类的数据属性都变成大写。
19、编写程序, 在元类中控制自定义的类无需init方法.
20、编写程序, 编写一个学生类, 要求有一个计数器的属性, 统计总共实例化了多少个学生.
21、编写程序, A 继承了 B, 俩个类都实现了 handle 方法, 在 A 中的 handle 方法中调用 B 的 handle 方法
22、编写程序, 如下有三点要求:
①自定义用户信息数据结构, 写入文件, 然后读取出内容, 利用json模块进行数据的序列化和反序列化
e.g
{
"egon":{"password":"123",'status':False,'timeout':0},
"alex":{"password":"456",'status':False,'timeout':0},
}
②定义用户类,定义方法db,例如 执行obj.db可以拿到用户数据结构
③在该类中实现登录、退出方法, 登录成功将状态(status)修改为True, 退出将状态修改为False(退出要判断是否处于登录状态).密码输入错误三次将设置锁定时间(下次登录如果和当前时间比较大于10秒即不允许登录)
23、在该类中实现登录、退出方法, 登录成功将状态(status)修改为True, 退出将状态修改为False(退出要判断是否处于登录状态).密码输入错误三次将设置锁定时间(下次登录如果和当前时间比较大于10秒即不允许登录)。
.
|-- bin/
| |-- main.py 程序运行主体程序(可进行菜单选择等)
|-- config/
| |-- settings.py 程序配置(例如: 配置存储创建老师的路径相关等)
|-- db 数据存储(持久化, 使得每次再重启程序时, 相关数据对应保留)
| |-- teachers/ 存储所有老师的文件
| |-- ... ...
|-- src/ 程序主体模块存放
| |-- __init__.py
| |-- teacher.py 例如: 实现老师相关功能的文件
| |-- group.py 例如: 实现班级相关的功能的文件
|-- manage.py 程序启动文件
|-- README.md 程序说明文件
24、根据23 题, 再编写一个班级类, 实现以下功能, 创建班级, 删除班级, 获取班级列表、创建成功之后通过 pickle 序列化保存到文件里,并在下一次重启程序时能,读取到创建的班级.。
25、根据 23题, 编写课程类, 实现以下功能, 创建课程(创建要求如上), 删除课程, 获取课程列表。
26、根据23 题, 编写学校类, 实现以下功能, 创建学校, 删除学校, 获取学校列表
27、通过23题, 它们雷同的功能, 是否可以通过继承的方式进行一些优化。
伪代码
class Behavior(object):
def fetch(self, keyword):
通过 keyword 参数 查询出对应的数据列表
class School(Behavior):
pass
class Teacher(Behavior):
pass
s = School()
t = Teacher()
s.fetch("school")
t.fetch("teacher")
4️⃣ 综合作业--选课系统开发,要求有四种角色:学校、学员、课程、讲师
要求:
(1)创建北京、上海 2 所学校
(2)创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开
(3)课程包含,周期,价格,通过学校创建课程
(4)通过学校创建班级, 班级关联课程、讲师
(5)创建学员时,选择学校,关联班级
(6)创建讲师角色时要关联学校
(7)提供两个角色接口
(8)为学员、讲师、管理员分别提供用户界面,并提供对应功能: 1 学员视图, 可以注册, 交学费, 选择班级, 2 讲师视图, 讲师可管理自己的班级, 上课时选择班级, 查看班级学员列表 , 修改所管理的学员的成绩 3 管理视图,创建讲师, 创建班级,创建课程
注:上面的操作产生的数据都通过pickle序列化保存到文件里 注2:此作业必须画流程图,图中标注好不同类或对象之间的调用关系