Python面向对象编程 Object Oriented Programming(OOP)----封装
首先明白面向对象和面向过程具体的区别和特点,有利于更好的明白它们各自的优势
面向过程
- 把完成某一个需求的
所有步骤
从头到尾
逐步实现 - 根据开发需求,将某些 功能独立 的代码 封装 成一个又一个 函数
- 最后完成的代码,就是顺序地调用 不同的函数
特点
- 注重 步骤与过程,不注重职责分工
- 如果需求复杂,代码会变得很复杂
- 开发复杂项目,没有固定的套路,开发难度很大!
面向对象
- 在完成某一个需求前,首先确定 职责 —— 要做的事情(方法)
- 根据 职责 确定不同的 对象,在 对象 内部封装不同的 方法(多个)
- 最后完成的代码,就是顺序地让
不同的对象
调用不同的方法
特点
- 注重 对象和职责,不同的对象承担不同的职责
- 更加适合应对复杂的需求变化,是专门应对复杂项目开发,提供的固定套路
- 需要在面向过程基础上,再学习一些面向对象的语法
知道了面向对象和面向过程的区别和特点,我们需要了解面向对象的两个核心概念 类 和 对象
类和对象
类
- 类是对一群具有 相同 特征 或者 行为 的事物的一个统称,是抽象的,不能直接使用,特征 被称为 属性,行为 被称为 方法
- 类 就相当于制造飞机时的图纸,是一个 模板,是 负责创建对象的
对象
- 对象 是 由类创建出来的一个具体存在,可以直接使用
- 由 哪一个类 创建出来的 对象,就拥有在 哪一个类 中定义的:
属性和方法
- 对象 就相当于用 图纸 制造 的飞机
class Person: # 类就是抽象的一般对象,含有对象共有的属和方法,一个类可以有多个对象
name = ''
age = 0
def works(self):
self.work = ''
pass
if __name__ == '__main__':
xiaoming = Person() # 用Person类实例化一个xiaoming对象,我们可以对该对象的属性进行赋值,可以调用该对象所属类的方法
xiaoming.name = '小明'
xiaoming.age = 18
xiaoming.work = '学生'
学习完类和对象的定义和关系,接下俩就是具体进行类的封装和实例化对象
常用类函数
序号 | 方法名 | 类型 | 作用 | 备注 |
01 |
| 方法 | 创建对象时,会被 自动 调用 | 类比C++的无参构造 |
02 |
| 方法 | 对象被初始化时,会被 自动 调用 | 类比C++含参构造函数 |
03 |
| 方法 | 对象被从内存中销毁前,会被 自动 调用 | 类比C++析构函数 |
04 |
| 方法 | 返回对象的描述信息, | Python独有 |
__init__
调用时机: 在创建对象之后,会立即调用.
作用:
1. 用来给对象添加属性,给对象属性一个初始值(构造函数)
2. 代码的业务需求,每创建一个对象,都需要执行的代码可以写在 __init__
中
注意点: 如果 __init__
方法中,给出了 self 之外的形参,那么在创建的对象的时候,需要给额外的形参传递实参值 类名(实参)
-__str__
调用时机:
1.print(对象)
, 会自动调用__str__
方法, 打印输出的结果是__str__
方法的返回值
2.str(对象)
类型转换,将自定义对象转换为字符串的时候, 会自动调用
作用:
1. 打印对象的时候,输出一些属性信息
2. 需要将对象转换为字符串类型的时候
注意点:方法必须返回一个字符串
,只有 self 一个参数
__del__
调用时机: 就是析构函数
对象在内存中被销毁删除的时候(引用计数为 0)会自动调用 del 方法
1. 程序代码运行结束,在程序运行过程中,创建的所有对象和变量都会被删除销毁
2. 使用del 变量
, 将这个对象的引用计数变为 0(就是从内存中删除数据),会自动调用 del 方法
作用:
对象被删除销毁的时候,要书写的代码可以写在 __del__
中,一般很少使用
self变量
由 哪一个对象 调用的方法,方法内的
self
就是 哪一个对象的引用,和C++中的this指针相同,区别是C++中的this不在参数列表中,隐式存在,Python中,是显含在参数列表中的,以默认形参存在,程序员调用时不用传入
- 在类封装的方法内部,
self
就表示 当前调用方法的对象自己 - 调用方法时,程序员不需要传递
self
参数 - 在方法内部
- 可以通过
self.
访问对象的属性 - 也可以通过
self.
调用其他的对象方法
- 在
继承
中,需要明白什么时候需要在调用方法的括号中加self
,什么时候需要在属性前加self
初始化对象时设置初始值
类似于C++中的含参构造函数
class A:
def __init__(self,name,age):
self.name = name # 这里也可以定义默认参数
self.age = age
def show(self):
print("我叫%s,今年%d"%(self.name,self.age))
if __name__ == '__main__':
a = A("小明",18) # 通过传入参数设置初始值
a.show() # 我叫小明,今年18
具体案列
针对面向对象,多练习一些例子,明白如何封装,如何调用,会加快自己对面向对象 的理解
具体步骤:
1.第一步 —— 将 属性 和 方法 封装 到一个抽象的 类 中
2.外界 使用 类 创建 对象,然后 让对象调用方法
3.对象方法的细节 都被 封装 在 类的内部
案列1
小明 和 小美 都爱跑步, 小明 体重 75.0
公斤, 小美 体重 45.0
公斤, 每次 跑步 都会减少 0.5
公斤,每次 吃东西 都会增加 1
公斤,在进行多次跑步和吃东西操作之后,打印小明和小美的体重
分析
小明和小美都是对象,是Person类的实例化对象,题目要求有吃东西
和跑步
两种操作,则Person类中有该两种方法,需要输出体重,则可以通过__str__函数返回该对象体重
例
class Person:
def __init__(self,name,weight):
self.name = name
self.weight = weight
def eat(self):
self.weight += 1.0
def run(self):
self.weight -= 0.5
def __str__(self):
return "我叫%s,现在的体重为%.02fkg"%(self.name,self.weight)
# 这里稍微注意一下输出格式,因为如果用%d,则会之间舍弃小数,应该用%.02f输出格式
if __name__ == '__main__':
xiaoming = Person("xiaoming",75)
xiaomei =Person("xiaomei",45)
print(xiaoming) # 我叫xiaoming,现在的体重为75.00kg
print(xiaomei) # 我叫xiaomei,现在的体重为45.00kg
xiaoming.eat()
xiaoming.run()
print(xiaoming) # 我叫xiaoming,现在的体重为75.50kg
xiaomei.run()
xiaomei.eat()
print(xiaomei) # 我叫xiaomei,现在的体重为45.50kg
案列2
1.定义一个Furniture
类,初始化定义name
和area
属性
2.创建一个类Home
,初始化地址address
房屋面积area
, 家具列表list
属性
3.定义方法add_furniture 容纳家具 添加家具,并且计算剩余面积
4.创建一个对象jia1(北京, 占地面积1000),创建对象双人床bed,sofa 分别占地面积6,10添加到jia1中,计算剩余面积,并且打印
打印格式是房子地理位置在xx,房子面积xx,剩余面积是xx,家具有xx
分析
宏观上可知是定义两个类,一个是Fruniture类,一个是Home类,实例化两个Fruniture对象sofe和bed,将这两个对象添加到Home对象jia1中.
微观上,Home类中应该有属性,家具列表,地址,房屋面积,剩余面积,方法有添加家具,Fruniture类中有属性:名字,占地面积,剩下的就是细节完善
class Fruniture:
def __init__(self,name,area):
self.name = name
self.area = area
class Home:
list = []
def __init__(self,address,area):
self.address = address
self.area = area
self.remaing = area
def add_fruniture(self,fru):
self.list.append(fru)
self.remaing = self.remaing - fru.area
def pr(self):
print("房子地理位置在", self.address, "房子面积:", self.area, "剩余面积是:",self.remaing, "家具有:", end="")
for x in jia1.list: # 这里利用x在list中遍历 是遍历对象 要想拿出名字,还需要.name
print(x.name, end=",")
if __name__ == '__main__':
jia1 = Home("北京",1000)
bed = Fruniture("双人床",6)
sofa = Fruniture("沙发",10)
jia1.add_fruniture(bed)
jia1.add_fruniture(sofa)
jia1.pr()
# 房子地理位置在 北京 房子面积: 1000 剩余面积是: 984 家具有:双人床,沙发,