27、面向对象
一、面向对象的介绍
1.1、面向对象以及面向过程的对比
1.1.1、面向过程:
核心:过程
目的:将程序流程化,按照步骤依次进行
1.1.2、面向对象:
核心:对象
目的:将程序整合,对象相当于容器,用来盛放数据和功能
1.1.3、面向类:
核心:类(同类)
目的:将程序整合,类也是容器,用来盛放同类对象相同的数据和功能,可以算是对象中的一种
1.1.4、面向对象的特点
程序=数据+功能,即变量+函数。Python就是一种基于面向对象的语言,使其组合在一起。
面向对象可以有效的提高程序的可延展性
1.2、对象的组合
1.2.1、对象不传值
def tell_stu_info(stu_obj): print('学生信息:名字:%s 年龄:%s 性别:%s' %( stu_obj['stu_name'], stu_obj['stu_age'], stu_obj['stu_gender'] ))
1.2.2、对象传值
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.3、函数内套对象
stu_obj={ 'stu_school':'oldboy', 'stu_name':'egon', 'stu_age':18, 'stu_gender':'male', 'tell_stu_info': tell_stu_info, 'set_info':set_info
二、实现面向对象的编程
2.1、先定义类
类是相似的数据与功能的集合体
所以类体中最常见的是变量以及函数,但类体也是可以包含其他任意代码的
注意:类体代码是在定义时就会直接执行的,并且产生名称空间
2.2、类体的表达
class Student: #先定义类体 class 类体名开头要大写 # 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('========>') #类体在定义时直接执行 # print(Student.__dict__) #查看类体在定义时的地址
2.3、属性访问的语法
访问类体中属性的语法,需要分别访问数据以及功能的,他们的访问方式是不一样的
2.3.1、访问数据的语法 类体名.变量名
print(Student.stu_school) # Student.__dict__['stu_school']
2.3.2、访问功能的语法 类体名.函数名
# print(Student.set_info) # Student.__dict__['set_info']
2.4、调用类。也叫实例化对象,赋值给对象 赋值于变量名=类体( )
stu1_obj=Student() stu2_obj=Student() stu3_obj=Student()
2.5、为对象定制自己独有的属性
会出现以下两个问题:
1.代码重复
2.属性的查找顺序
j.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__) #第三组数据
解决问题一:
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') #再分别将变量进行赋值
解决问题二:
# 一:先定义类 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'] )) # 二:再调用类产生对象 #实例化对象,即给空对象赋值 stu1_obj=Student('egon',18,'male') # Student.__init__(空对象,'egon',18,'male') # stu2_obj=Student('lili',19,'female') # stu3_obj=Student('jack',20,'male')
2.6、实例化时发生的事
1.先产生一个空对象
2.python会自动调用类中的__init__方法然将空对象已经调用类时括号内传入的参数一同传给__init__方法
3.返回初始完的对象
2.7、制定空对象时,__init__的使用方法
1.会在调用类的时候自动触发,用来为对象初始化自己独有的数据
2.__init__内存放的是为对象初始化属性的功能,也可以存放其他的代码,想要在调用时立即执行的代码都可以放到里面
3.__init__方法必须返回None
三、属性查找
3.1、类中存放的是对象共有的数据与功能
3.1.1、类可以访问类的数据属性 类体名.变量名
print(Student.stu_school)
3.1.2、类可以访问类的功能属性 类体名.函数名
print(Student.set_info) # Student.__dict__['set_info']
3.2、类的数据属性
由于类的数据属性都是共用的,所以访问的地址都是一样的
print(id(Student.stu_school)) print(id(stu1_obj.stu_school)) print(id(stu2_obj.stu_school)) print(id(stu3_obj.stu_school)) # id都一样
3.3、类的功能属性
类的函数功能主要是给对象使用的,并且是绑定给对象,虽然大家访问到的属性的地址是相同的功能,但绑定到不同的对象就是不同的方法,内存地址各不相同。
这就涉及到对象属性访问顺序了。
如果对象有这个属性即用对象自己的,如果对象没有就从类里面找,找到就用找不到就报错。
如果对象都没有添加其他的属性,那大家访问到的都是类中的,所以他们的id地址是相同的
但如果某个对象偷偷添加了自己的属性,那的对象是不会变的。再次访问时,有这个属性的对象就用自己的,没有就用类的。
# 绑定方法的特殊之处在于:谁来调用绑定方法就会将谁当做第一个参数自动传入 # print(Student.tell_stu_info) # print(stu1_obj.tell_stu_info) # print(stu2_obj.tell_stu_info) # print(stu3_obj.tell_stu_info)