python面向对象编程
面向对象编程
面向过程编程与面向对象编程对比
面向过程编程
面向过程编程:核心是'过程'二字。
过程即解决问题的步骤, 即先干什么 在干什么 最后干什么
就是在设计一条条的'流水线'
举例:
1.把大象放进冰箱中需要几步:
'''
1. 把冰箱门打开
2. 把大象放进去
3. 关上冰箱门
'''
面向过程优点:复杂的问题流程化,进而简单化
面向过程缺点:牵一发而动全身,扩展性差,可维护性差
应用场景:对扩展性要求不高的地方。 eg:安装包的使用
# 注册的功能
'''
1.用户输入用户名和密码
2.验证参数
3.写入文件,注册成功
'''
面向对象编程
面向对象编程:核心即'对象'二字
对象指的是盛放'相关的'数据与功能的容器
# 以学生选课系统为例:
1. 数据:学生的数据 老师的数据
2. 功能: 选课功能等 老师相关的功能
这样就可以分为两个容器盛放
eg:
# 如果把”数据“比喻为”睫毛膏“、”眼影“、”唇彩“等化妆所需要的原材料;把”功能“比喻为眼线笔、眉笔等化妆所需要的工具,那么”对象“就是一个彩妆盒,彩妆盒可以把”原材料“与”工具“都装到一起
## 这样:如果我们把”化妆“比喻为要执行的业务逻辑,此时只需要拿来一样东西即可,那就是彩妆盒,因为彩妆盒里整合了化妆所需的所有原材料与功能,这比起你分别拿来原材料与功能才能执行,要方便的多。
优点:扩展性强,可维护性强
缺点:相对于面向过程编程的复杂度高
基于该思想编写程序: 就是在创造一个一个的容器 来把相关的东西盛放到一起
# 一定要用对场景 不要想到有扩展性的就必须要用面向对象编程。
对象代码示例
学生选课系统
# 定义学生的基本信息
stu1_name = 'jason'
stu1_age = '19'
sut1_gender = 'male'
stu1_courses = []
stu2_name = 'gary'
stu2_age = '19'
sut2_gender = 'male'
stu2_courses = []
def choice_coures(stu_name,stu_course,course):
stu_course.append(course)
print('%s添加课程%s'%(stu_name,course))
choice_coures(stu1_name,stu1_courses,'python')
choice_coures(stu2_name,stu2_courses,'运维linux')
# 这是原先写程序的思路
# 这里定义了两个学生选课 如果说有成千上万的学生 这样的结果......
# 怎么样让他简洁一点
版本er:# 把相关的功能放到一块
sut1_dic={
'stu_name' :'jason',
'stu_age' :'19',
'sut_gender' : 'male',
'stu_courses' : []
}
sut2_dic={
'stu_name' :'gary',
'stu_age' :'20',
'sut_gender' : 'female',
'stu_courses' : []
}
# 这样就只需要定义两个变量就可以
def choice_coures(stu_dic,course):
stu_dic['stu_courses'].append(course)
print('%s添加课程%s'%(stu_dic['stu_name'],course))
choice_coures(sut1_dic,'python')
choice_coures(sut2_dic,'运维')
# 版本三
def choice_coures(stu_dic, course):
stu_dic['stu_courses'].append(course)
print('%s添加课程%s' % (stu_dic['stu_name'], course))
# 这就是对象 (把相关的数据与功能发到一个容器里)
# 如果这里有老师的权限功能就不合适了
sut1_dic = {
'stu_name': 'jason',
'stu_age': '19',
'sut_gender': 'male',
'stu_courses': [],
'choice_courses': choice_coures
}
sut2_dic = {
'stu_name': 'gary',
'stu_age': '20',
'sut_gender': 'female',
'stu_courses': [],
'choice_courses': choice_coures
}
sut1_dic['choice_courses'](sut1_dic,'python课程')
sut2_dic['choice_courses'](sut2_dic,'运维开发课程')
# 但是这样还是未解决代码冗余的状况 函数的定义也没有写到容器里去
故接下来就用到'类'来解决这个问题
类的定义和对象的产生
类: 特征与技能的结合体
类: 用来解决对象之间代码冗余问题
eg:学生选课系统 学生共有的数据和功能 ('学校',选课功能)
### 即 class语法
到底是先有类还是现有对象呢?
1.程序中:
必须先定义类,然后调用类产生对象
2. 先使生活中:
现有对象,再有类
定义类和定义函数区别:
1.定义函数
def 函数名():
pass
2. 定义类:
def 类名():
pass
'''
定义类都发生了什么事:
1. 会直接执行类体代码
2. 产生一个类的名称空间 用来将类体代码运行过程中产生的名字丢进去
3. 将名称空间的内存地址绑定给类名
'''
# 类名一般情况首字母大写
class Student:
# 定义一个属性
school = 'SH'
#定义一个技能(函数)
def choose_course(stu_dict, course):
stu_dict['course'].append(course)
print('%s选课成功 %s' % (stu_dict['name'], stu_dict['course']))
# 查看类的名称空间
pring(Student.__dict__)
# 产生对象(调用类)
stu1_dic = Student() # 产生一个空字典指向类
stu2_dic = Student() # 产生一个空字典指向类
# 调用类产生对象,默认产生的就是一个空字典
print(stu1_dic.school)
# 此时先去自己的名称空间中找school变量 如果没有就去类的名称空间中找
print(stu1_dic.__dict__.school)
# 此时只去自己的名称空间中找school 如果没有就会报错 所以不要去自己的名称空间中找
# python默认.的方式直接去访问属性 如果自己名称空间没有就去类的名称空间中找
版本2:
class Student: # 定义一个类 造了一个共享字典 把共享的数据和方法扔进去
school = 'SH'
def choice_coures(stu_dic, course):
stu_dic['stu_courses'].append(course)
print('%s添加课程%s' % (stu_dic['stu_name'], course))
stu1_dic = Student() # 造出一个空对象(空字典)
stu2_dic = Student()
def init(stu_dic,name,age,courses = None):
if courses is None: # 如果用户没有穿参数默认空列表
courses = []
stu_dic.name = name # 往对象的空字典添加独有的东西
stu_dic.age = age
stu_dic.courses = courses
init(stu1_dic,'jason',29,'linux')
print(stu1_dic.__dict__) # 这个是查看自身名称空间中的名字
print(stu1_dic.name) # 可直接用.的方式去访问(先去自身查找name再去类名称空间中查找)
# 这里就解决的代码冗余的问题 但是还是手动创建很多空对象
__init__方法
# 版本3 最终版本
class Student:
school = 'SH'
def __init__(stu_dic, name, age, courses=None):
if courses is None:
courses = []
stu_dic.name = name
stu_dic.age = age
stu_dic.courses = courses
def choice_coures(stu_dic, course):
stu_dic['stu_courses'].append(course)
print('%s添加课程%s' % (stu_dic['stu_name'], course))
# 函数在调用阶段发生了三件事
'''
1. 会自动创建空对象(空字典)(调用__new__来创建的空对象)
2. 会自动触发__init__函数的运行,__init__(第一个参数自动传:空对象,name,age,courses),完成对象的初始化操作
3. 返回该对象,赋值给变量名stu1_dic
'''
stu1_dic = Student('jason',20,'python')
# 注意:__init__ 不能有返回值