今日目标
- 理解面向对象的思想
- 掌握类与对象的概念和使用
- 掌握对象初始化的__init__方法
面向对象编程「理解」
OOP,Object Oriented Programming
什么是面向对象思想
面向对象思想指的是一种编程思想(编程范式),相对于面向过程而言,只关心哪个对象完成这个功能,它关注的是完成功能的结果。它决定了编写代码的一种习惯和流程。
不同的语言会有不同的实现(python,java,php,c++,js…)。
面向过程和面向对象的区别
思考
如何把一头大象装进冰箱里?
面向过程实现
- 创建冰箱打开的方法;
- 创建把大象塞进冰箱的方法;
- 创建把冰箱门关闭的方法;
- 创建main方法,依次调用上面3个方法;
面向对象实现
- 创建一个大象的类,里面有个大象进冰箱的方法;
- 创建一个冰箱的类,里面有打开冰箱和关闭冰箱的两个方法;
- 创建main方法,通过大象和冰箱的类创建大象和冰箱的对象;
- 冰箱的对象调用打开冰箱方法,大象对象调用进冰箱的方法,冰箱对象调用关闭冰箱的方法;
面向过程(怎么做)
概念
关注解决问题的步骤 。
面向过程编程的实现大概分三步:
- 根据需求从头到尾逐步实现我们的功能
- 将某些具有独立功能的代码块封装成函数
- 最终完成代码,按照需求按次序调用函数
特点
面向过程的编程有以下的特点,或者说是缺点:
- 注重步骤和过程,不注重职责的分工
- 当需求变得更多更复杂,我们的函数也会相应变多变复杂
- 当开发复杂项目的时候,我们没有一个固定的模式开发,难度会非常的大 (乐高,如果没有模块和颜色分类就很难拼好)
面向对象(谁来做)
概念
关注解决问题的这个对象,谁帮我解决问题 。
相比较函数,面向对象是更大的封装,根据职责在一个对象中封装多个方法。
- 在完成一个需求之前,首先确定职责 -----要做的事情(方法)
- 根据职责确定不同的对象,在对象内部封装不同的方法(多个)
- 最后完成的代码,就是顺序地让不同的对象调用不同的方法
特点
- 注重对象和职责,不同的对象承担不同的职责
- 更加适合应对复杂的需求变化,是专门应对复杂项目开发,提供的固定套路
- 需要在面向过程基础上,再学习一些面向对象的语法
这个游戏就是每个对象负责不同的方法,比如向日葵有自己的方法,有一定生命值不是被僵尸咬一口就立即死翘翘了,也能产阳关和没事在那摇摇晃晃。同样每一个植物或者僵尸都和向日葵差不多,都有属于自己的职责(方法)。面向对象的对象内部方法不像面向过程遇到大型项目方之间会彼此调用,让项目代码变得复杂冗长。面向对象之间的方法极少会被调用,这也就是说面向对象更加适合应对复杂的需求变化,是专门应对复杂项目开发,提供的固定套路。
面向对象语法「重点」
类和对象的概念「理解」
类
是对具有相同特征或者行为的事物(指多个事物)的一个统称,是抽象的,不能直接使用。
对象
对象也叫作 类的实例
是由类创建出来的一个具体存在的事物(单个事物),可以直接使用。
说明:由哪一个类创建出来的对象,就拥有在哪一个类中定义的属性和方法。
苹果-->类
红苹果-->类
张三手里的那个红苹果-->对象
狗-->类
大黄狗-->类
李四家的那条大黄狗-->对象
类的构成
类的三要素
类名
- 遵循标识符的命名规范
- 一般使用大驼峰命名法
- 见名知意
class 类名:
pass
属性
事物的特征
方法
事物的行为
在类的内部定义
第一个参数必须是self, self指向调用这个方法的对象
其他定义以及使用方式和函数相同
class ClassName:
def fn(self):
pass
面向对象代码的步骤
- 设计类(类的三要素)
- 定义类
- 创建对象(实例化对象)
- 由对象调用类中的方法
类的设计「掌握」
根据类的三要素设计。
案例
类名,属性,方法类名:人类 Person,People,Human
属性:姓名(name),年龄(age),身高(height)
方法:跑(run)/吃(eat)
定义类
# 定义类使用关键字class
# 第一种方式 [推荐]
class Name1:
pass
# 封装实现类的代码
# 第二种方式
class Name2():
pass
# 第三种方式
class Name3(object):
pass
# 在python3中,以上三种方式没有区别
创建对象(实例化对象)
在代码中,对象是由类创建。
类名() # 就是创建对象
# 一般使用变量将创建的对象保存起来
变量 = 类名() # 一般将这个变量称为是对象,本质上变量保存的是对象的引用地址
说明:
- 类可以实例化多个对象
- 对象之间是隔离的,每创建一个新的对象都会开辟一个新的内存空间来进行存储
# 先有类,通过类创建对象
# 定义了一个Student类
class Student:
pass
# 通过类创建(实例化)对象
# object 中文意思 对象
# 一个类类可以创建多个对象
# 类名()
# 通过类名()创建出一个类的实例(对象)
student1 = Student()
print(hex(id(student1))) # 通过id查看的内存地址是10进制
print(student1) # 直接打印对象查看的16进制
student2 = Student()
print(student2)
调用类中的方法
由类创建的对象,可以调用类中的方法
语法:
对象.方法名()
案例
class Student:
def eat(self):
print("学生正在吃饭")
xiaoming = Student()
xiaoming.eat()
---------------
打印结果:学生正在吃饭
self参数
- 从函数的语法上来看,self是形参,名字可以是任意的变量名,只是我们习惯性叫self;
- 特殊点:self是一个普通的参数,按照函数的语法,在调用的时候,必须传递实参值。原因,是Python解释器自动的将调用这个方法的对象作为参数传递给self,所以self就是调用这个方法的对象(谁调用这个方法,谁就是self);
class Student:
def eat(self):
print(f'self:{id(self)}')
print("学生正在吃饭")
xiaoming = Student()
print(f'xiaoming:{id(xiaoming)}')
xiaoming.eat() # xiaoming调用,self就是xiaoming
xiaohong = Student()
print(f'xiaohong:{id(xiaohong)}')
xiaohong.eat() # xiaohong调用,self就是xiaohong
--------------------
打印结果:
xiaoming:1353947243760
self:1353947243760
学生正在吃饭
xiaohong:1353947306736
self:1353947306736
学生正在吃饭
对象属性操作
类的外部
- 设置属性
object.attr = value
- 获取属性
object.atrr
- 修改属性(存在就是修改,不存在就是设置)
object.attr = value
- 删除属性
del object.attr
# 对象属性添加
class Student:
pass
# 类的外部设置对象属性
student1 = Student()
# 对象.属性名 = 属性值
student1.name = '张三'
student1.age = 18
# 获取对象属性
# 对象.属性名
print(student1.name)
# print(student1.addr) # 获取不存在的属性会抛出错误
# 修改对象属性
# 属性存在就修改,不存在就设置
# 对象.属性名 = 属性值
student1.name = '李四'
print(student1.name)
# 删除属性
del student1.name
print(student1.name)
类的内部
- 设置属性
__init__
初始化属性- 对象方法 设置属性
- 获取属性
- 对象方法 self.attr
- 修改属性
- 对象方法 修改属性
- 删除属性
- 对象方法 删除属性
# 定义类
# 类的内部属性操作
class Phone():
# 属性设置
# 为手机设置品牌名称的方法
def setattrs(self, brand, color):
# obj.attr = value
self.brand = brand
self.color = color
# 获取属性
# 获取品牌
def getBrand(self):
print(self.brand)
# 获取颜色
def getColor(self):
print(self.color)
# 删除属性
def delBrand(self):
del self.brand
def delColor(self):
del self.color
# 创建对象
phone1 = Phone()
phone1.setattrs('小米', 'red')
# print(phone1.brand)
phone1.getBrand()
phone1.getColor()
phone1.setattrs('华为', 'black')
print(phone1.brand)
print(phone1.color)
phone1.delColor()
print(phone1.color)
魔术(法)方法
什么是魔术方法
- python类中内置的具有特殊功能的方法
- 魔术方法不需要我们手动调用
- 在对类的实例进行一些操作的时候会触发魔术方法的执行
- 魔术方法的命名方式:
__名字__()
init()方法「掌握」
构造函数,对象初始化方法
是一种特殊的方法,主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值。
触发时机
对象创建时,自动执行这个方法
作用
用来初始化对象的属性
语法
class 类名:
# 名字固定不可变
def __init__(self,[参数列表]):
# 初始化操作
案例
- 方法设置的⾃定义参数必须和创建对象时传递的参数保持⼀致
# init对象初始化方法
'''
# 初始化
class Student:
def __init__(self):
print("对象创建后执行这个方法")
s = Student()
'''
# 初始化参数
class Student:
def __init__(self, name, age):
# 对象属性初始化
self.name = name
self.age = age
s1 = Student('zs', 18)
print(s1.name)
print(s1.age)
s2 = Student('lisi', 20)
print(s2.name)
print(s2.age)
str()方法「了解」
触发机制
当对象被print打印的时候,触发str方法执行。
作用
默认print打印对象,输出的是对象的地址,通过str方法可以返回自定义的一个字符串。
使用注意
str方法必须返回字符串类型,不能自定义参数。
语法
class 类名:
# 名字固定不可变
def __str__(self):
return "对象描述信息的字符串"
案例
# str方法
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
# str返回的必须是字符串类型
return f"我的名字为{self.name},我的年龄为{self.age}。"
s1 = Student('张三', 18)
print(s1)
s2 = Student('李四', 20)
print(s2)
del()方法「了解」
析构函数
析构函数(destructor) 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作。
Tips:
python是垃圾自动回收的,不需要我们显式的销毁对象,当没有引用指向内存中的对象时,即引用计数为0时自动销毁。当有一个变量保存了某个对象的引用时,此对象的引用计数器就会加1。当执行del obj时会调用对象的__del__方法,这时对象的引用计数会减1,当对象的引用计数为0时,对象会被销毁,内存就会被回收。
触发机制
当对象被销毁时执行这个方法
作用
在对象被销毁时,可以做一些收尾工作
语法
class 类名:
# 名字固定不可变
def __del__(self):
# 触发对象销毁时的一些操作
案例1
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __del__(self):
print("__del__方法自动被调用执行")
xiaoqiao = Student('小乔', 16)
print('-------代码最后一行--------')
案例2
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __del__(self):
print("__del__方法自动被调用执行")
# 创建类的实例
xiaoqiao = Student('小乔', 16)
xiaoqiao2 = xiaoqiao
print(xiaoqiao)
print(xiaoqiao2)
del xiaoqiao # 对象在内存中销毁才会触发del方法执行
print(11111111111)
print('-------代码最后一行--------')