27---面向对象编程思想
一 面向过程与面向对象
-
面向过程
''' 面向过程: 核心:过程 过程的终极奥义就是将程序流程化 过程就是'流水线',用来分步骤解决问题 '''
-
面向对象
''' 面向对象: 核心:对象 对象的终极奥义就是将程序'整合' 对象是'容器':用来盛放数据与功能的 类也是'容器':该容器用来存放同类对象共有的数据与功能 '''
二 面向对象---如何一步一步进行整合
-
整合引入---化妆盒
如果我们把”化妆“比喻为要执行的业务逻辑,此时只需要拿来一样东西即可,那就是彩妆盒,因为彩妆盒里整合了化妆所需的所有原材料与功能,这比起你分别拿来原材料与功能才能执行,要方便的多。
-
程序 = 数据 + 功能
- 1 未学函数之前读取信息
# 所有的程序都是由”数据”与“功能“组成,因而编写程序的本质就是定义出一系列的数据,然后定义出一系列的功能来对数据进行操作。在学习”对象“之前,程序中的数据与功能是分离开的,如下 name = '如花' age = 18 gender = 'male' print(f'{name} {age} {gender}')
- 2 学函数后---可以通过定义函数读取信息
name = '如花' age = 18 gender = 'male' # 函数整合:读取信息 def tell_info(): print(f'{name} {age} {gender}') # 修改信息 def set(x,y,z): global name,age,gender name = x age = y gender = z
-
3 可以将上述代码存入文件中,变成模块,但是每产生一个新的功能就创建一个新的文件并不方便管理。
-
4 可以使用字典将数据和功能整合到一起
name = '如花' age = 18 gender = 'male' # 函数整合:读取信息 def tell_info(name,age,gender): print(f'{name} {age} {gender}') # 修改信息 def set(x,y,z): global name,age,gender name = x age = y gender = z # 数据和功能整合到字典中 user_info = { 'name':'如花', 'age':18, 'gender':'male', 'tell_info':tell_info, 'set':set }
-
5 对4进行进一步修改,将功能函数需要的参数通过字典传值
# 可以通过传字典的方式给函数内需要参数的地方传值 # :读取信息 def tell_info(user_info): name = user_info['name'] age = user_info['age'] gender = user_info['gender'] print(f'{name} {age} {gender}') # 修改信息 def set(user_info,x,y,z): user_info['name'] = x user_info['age'] = y user_info['gender'] = z user_info = { 'name':'如花', 'age':18, 'gender':'male', 'tell_info':tell_info, 'set':set }
-
6 以上五种方式,最后一种是对数据和功能整合度最高的方式,但是定义的功能和字典还是分开的,那么python到底提供了何种方式或语法允许我们将数据和功能很好的整合在一起呢?....
三 类与对象
- 类
类即类别/种类,是面向对象分析和设计的基石,如果多个对象有相似的数据与功能,那么该多个对象就属于同一种类。
- 使用类的好处
可以把同一类对象相同的数据与功能存放到类里,而无需每个对象都重复存一份,这样每个对象里只需存自己独有的数据即可,极大地节省了空间。
如果说对象是用来存放数据与功能的容器,那么类则是用来存放多个对象相同的数据与功能的容器。
- 注意
在程序中,必须要事先定义类,然后再调用类产生对象(调用类拿到的返回值就是对象)。
产生对象的类与对象之间存在关联,这种关联指的是:对象可以访问到类中共有的数据与功能,所以类中的内容仍然是属于对象的,类只不过是一种节省空间、减少代码冗余的机制,面向对象编程最终的核心仍然是去使用对象。
四 实现面向对象的编程
-
先定义类
- 类
# 类是对象相似数据与功能的集合体 # 所以类体中最常见的是变量与函数的定义,但是类体其实是可以包含任意其他代码的 # 注意:类体代码是在类定义阶段就会立即执行,会产生类的名称空间
- 定义类
# 类名采用驼峰体 class Student: # 1、变量的定义 stu_school='oldboy' # 2、功能的定义 def tell_stu_info(stu_obj): print('学生信息:名字:%s 年龄:%s 性别:%s' %( stu_obj['stu_name'], stu_obj['stu_age'], stu_obj['stu_gender'] )) def set_info(stu_obj,x,y,z): stu_obj['stu_name']=x stu_obj['stu_age']=y stu_obj['stu_gender']=z
- 以字典方式输出类中存放的属性
print(Student.__dict__)
- 访问类的属性
# 属性访问的语法 # 1、访问数据属性 print(Student.stu_school) # Student.__dict__['stu_school'] # 2、访问函数属性 print(Student.set_info) # Student.__dict__['set_info'] # 3 增加类的属性 Student.x=1111 #Student.__dict__['x]=111 print(Student.__dict__)
-
再调用类产生对象
- 调用类产生对象
stu1_obj=Student() stu2_obj=Student() stu3_obj=Student() print(stu1_obj.__dict__) #{} print(stu2_obj.__dict__) #{} print(stu3_obj.__dict__) #{}
-
为对象定制独有的属性
- 解决方案一
stu1_obj.stu_name='egon' # stu1_obj.__dict__['stu_name']='egon' stu1_obj.stu_age=18 # stu1_obj.__dict__['stu_age']=18 stu1_obj.stu_gender='male' # stu1_obj.__dict__['stu_gender']='male' # print(stu1_obj.__dict__) stu2_obj.stu_name='lili' stu2_obj.stu_age=19 stu2_obj.stu_gender='female' # print(stu2_obj.__dict__) stu3_obj.stu_name='jack' stu3_obj.stu_age=20 stu3_obj.stu_gender='male' # print(stu2_obj.__dict__)
# 问题1:代码重复 # 问题2:属性的查找顺序
- 解决问题1--方案一
# 解决方案一:定义函数将重复的代码封装成函数 def init(obj,x,y,z): obj.stu_name=x obj.stu_age=y obj.stu_gender=z init(stu1_obj,'egon',18,'male') init(stu2_obj,'lili',19,'female') init(stu2_obj,'jack',20,'male')
方案一的问题:功能没有整合
- 解决问题1---方案二
将函数放在类体代码中,函数名规定为__init__
# 总结__init__方法 # 1、会在调用类时自动触发执行,用来为对象初始化自己独有的数据 # 2、__init__内应该存放是为对象初始化属性的功能,但是是可以存放任意其他代码,想要在 # 类调用时就立刻执行的代码都可以放到该方法内 # 3、__init__方法必须返回None
# 一:先定义类 class Student: # 1、变量的定义 stu_school='oldboy' # 空对象,'egon',18,'male' def __init__(obj,x,y,z): obj.stu_name=x # 空对象.stu_name='egon' obj.stu_age=y # 空对象.stu_age=18 obj.stu_gender=z # 空对象.stu_gender='male' # return None # 2、功能的定义 def tell_stu_info(stu_obj): print('学生信息:名字:%s 年龄:%s 性别:%s' %( stu_obj['stu_name'], stu_obj['stu_age'], stu_obj['stu_gender'] )) def set_info(stu_obj,x,y,z): stu_obj['stu_name']=x stu_obj['stu_age']=y stu_obj['stu_gender']=z
# 二:再调用类产生对象 # 调用类的过程又称之为实例化,发生了三件事 # 1、先产生一个空对象 # 2、python会自动调用类中的__init__方法然将空对象已经调用类时括号内传入的参数一同传给__init__方法 # 3、返回初始完的对象
stu1_obj=Student('egon',18,'male') # Student.__init__(空对象,'egon',18,'male') stu2_obj=Student('lili',19,'female') stu3_obj=Student('jack',20,'male') print(stu1_obj.__dict__) print(stu2_obj.__dict__) print(stu3_obj.__dict__)
五 属性查找
- 定义类和产生对象
class Student:
# 1、变量的定义
stu_school='oldboy'
count=0
# 空对象,'egon',18,'male'
def __init__(self,x,y,z):
Student.count += 1
self.stu_name=x # 空对象.stu_name='egon'
self.stu_age=y # 空对象.stu_age=18
self.stu_gender=z # 空对象.stu_gender='male'
# return None
# 2、功能的定义
def tell_stu_info(self):
print('学生信息:名字:%s 年龄:%s 性别:%s' %(
self.stu_name,
self.stu_age,
self.stu_gender
))
def set_info(self,x,y,z):
self.stu_name=x
self.stu_age=y
self.stu_gender=z
def choose(self,x):
print('正在选课')
self.course=x
stu1_obj=Student('egon',18,'male') # Student.__init__(空对象,'egon',18,'male')
stu2_obj=Student('lili',19,'female')
stu3_obj=Student('jack',20,'male')
print(stu1_obj.count) # 3
print(stu2_obj.count) # 3
print(stu3_obj.count) # 3
- 类中存放的是对象共有的数据和功能
- 类访问属性
# 1、类的数据属性
print(Student.stu_school)
# 2、类的函数属性
print(Student.tell_stu_info)
print(Student.set_info)
-
类中存放的属性是给对象使用的
-
类的【数据属性】是给所有对象共享的,所以内存地址是相同的
print(id(Student.stu_school))
print(id(stu1_obj.stu_school))
print(id(stu2_obj.stu_school))
print(id(stu3_obj.stu_school))
# 更改了类中的数据属性:即所有对象共有的属性值被改变了
Student.stu_school='OLDBOY'
# 只更改了stu1_obj对象的数据属性,对其他对象没有影响
stu1_obj.stu_school='OLDBOY'
-
类的【函数属性】主要是给对象使用的,而且是绑定给对象的,虽然所有对象指向的都是相同的功能,但是绑定到不同的对象就是不同的绑定方法,内存地址各不相同
- 类调用自己的函数属性必须严格按照函数的用法
# 类调用自己的函数属性必须严格按照函数的用法来 print(Student.tell_stu_info) print(Student.set_info) # tell_stu_info需要几个参数就必须传入几个参数 Student.tell_stu_info(stu1_obj) Student.tell_stu_info(stu2_obj) Student.tell_stu_info(stu3_obj) # set_info需要几个参数就必须传入几个参数 Student.set_info(stu1_obj,'EGON',19,'MALE') Student.tell_stu_info(stu1_obj)
- 对象使用【函数属性】--绑定方法的特殊之处在于:谁来调用绑定方法就会将谁当做第一个参数自动传入
print(Student.tell_stu_info) print(stu1_obj.tell_stu_info) print(stu2_obj.tell_stu_info) print(stu3_obj.tell_stu_info) stu1_obj.tell_stu_info() #tell_stu_info(stu1_obj) stu2_obj.tell_stu_info() #tell_stu_info(stu2_obj) stu3_obj.tell_stu_info() #tell_stu_info(stu3_obj) # 对象使用选课函数属性 stu1_obj.choose('python全栈开发') print(stu1_obj.course) stu2_obj.choose('linux运维') print(stu2_obj.course) stu3_obj.choose('高级架构师') print(stu3_obj.course)
六 属性查找举例----列表
l1=['aa','bb','cc'] # l=list([1,2,3])
l2=[111,222,333] # l=list([1,2,3])
print(l1.append)
print(list.append)
# 对象访问函数属性
l1.append('dd')
l2.append('dd')
print(l1)
print(l2)
# 类访问函属性
list.append(l1,'dd')
list.append(l2,'dd')
print(l1)
print(l2)