一、面向对象的思维方式
- 面向对象:是编程思想,不是技术,重在理解
- 思路:找到或者构造一个可以完成功能的主体,找到实体,功能完备,专注构造实体完成功能。
- 面向过程
- 思路:一步一步完成功能,自上而下,逐步细化。
- 关注点:分析代码实现的步骤。
简单区分:面向过程关心怎么做;面向对象关心谁来做。
二、类和对象
- 类:一系列拥有相同或者相似功能的对象集合,是一类事物的统称。
- 对象:类的具体的表现形式。
- 举例:手机就是类,苹果手机就是对象。
2.1 类的定义
- 经典类
class 类名: pass- 新式类(Python3 默认)
class 类名(object): pass2.2 类的实例化
- 实例化又叫创建对象。
- 实例化后的对象可以调用类中的方法。
- 一个类理论上可以创建无数个对象。
# 语法 对象名 = 类名()2.3 self 关键字
self:将调用方法的实例传入方法内部,在方法内部可以调用实例的属性和方法。
2.4 实例属性的添加和获取
在类的外部添加和获取实例属性
# 添加 对象名.属性名 = 值 # 获取 对象名.属性名创建对象后,对其中一个对象添加实例属性,其他对象不会发生变化。
在类的内部添加和获取实例属性
# 添加 self.属性名 = 值 # 获取 self.属性名实例属性一般写在实例方法中,调用该方法才会得到实例属性;一个实例调用,不会影响其余对象。
2.5__init__()初始化方法
__init__在创建对象、初始化对象时自动调用。- 在
__init__中添加的属性,每个对象都会拥有,称为共有属性。 - 在
__init__之外添加的属性,不是每个对象都拥有,称为独有属性。
带参数的__init__方法
- 创建对象时,
类名()括号内的参数会传递到__init__内部。 - 接收参数,可以动态给对象添加实例属性。
- 如果
__init__设置了形参,创建对象时必须传参,否则报错。
class Person(object): def __init__(self, name, age): self.name = name self.age = age p = Person("Rose",18)2.6__str__()方法
- 在类内部定义
__str__(),对象转为 str 类型时自动调用,return 返回对应数据。 __str__只能返回字符串类型。- 自动调用场景:
- 强制类型转换:
str(对象) - 隐式转换:
%s占位符接收对象、print(对象)打印对象。
- 强制类型转换:
2.7__del__()析构方法
- 对象释放销毁之前,自动执行
__del__。 - 对象释放的场景:
- 出了函数作用域后,局部变量被释放。
- 程序执行完成,所有变量被释放。
- 执行
del操作,可以提前释放变量。
class Person(object): def __init__(self,name,age): self.name=name self.age=age def __del__(self): print('我被释放了',self.name) p1=Person('Rose',18) # del p1 print('程序结束')重要结论: 对象被多个变量引用时,执行
del只是切断一个引用;必须切断全部引用,对象才会被释放。 函数内部局部变量,函数执行结束会释放;如果被全局变量引用,则不会释放。
p4 = None def func(): p3 = Person('笑傲',15) global p4 p4=p3 print(p3) func() print('程序结束了')三、面向对象的三大特性
3.1 封装
- 概念:将属性和方法写到类的内部,使用实例获取功能;可以设置私有权限,保障接口安全。
封装优点
- 对象完成整套业务,迭代维护方便。
- 设置私有属性 / 方法,提高代码安全性,只暴露需要对外的接口。
- 降低类与模块使用难度,少量接口即可完成功能。
私有属性、私有方法
- 只能在类内部调用,类外部无法访问。
- 格式:属性 / 方法前面加两条下划线
__。
get、set 方法
- get:获取私有属性;set:给私有属性赋值,类外部可以调用。
- 好处:读写数据时,可以做数据校验、数据加工。
3.2 继承
- 概念:子类对象可以使用父类中非私有属性和方法。
class 子类名(父类名): passobject是所有类的顶级基类。新式类括号不写父类,默认继承object。
单继承
- 一个子类只继承一个父类,支持多级继承。
- 子类可以使用父类所有非私有属性、方法。
- 如果父类
__init__带参数,子类实例化的时候必须传参。
多继承
- 一个子类同时继承多个父类。
class 子类名(父类1,父类2): pass- 子类可以使用多个父类非私有属性和方法。
- 如果父类存在同名方法 / 属性,优先使用靠前父类的内容。
子类重写父类方法
- 子类定义和父类同名方法,调用时执行子类方法,不再执行父类。
- 只要求方法名字相同,参数不需要校对。
- 查找顺序:优先找子类,再向上找父类。
子类调用父类方法
super().方法名(),调用直接父类方法父类名.方法名(self),指定父类调用,必须手动传入 selfsuper(当前类名, self).方法名()指定查找起始类
使用场景:重写父类方法之后,保留父类逻辑,做功能扩展。
3.3 多态
- 在继承关系中,子类重写父类同名方法;把不同子类对象传入函数,调用同一个方法,产生不同执行效果,称为多态。
- 前提:继承 + 方法重写。
3.4 类属性
- 类属性:定义在类内部、方法外部,属于全部对象共享;修改类属性,所有对象同步变化。
- 实例属性:对象独有;修改一个对象实例属性,不会影响其他对象。
3.5 类方法
- 适用场景:方法内部不需要实例属性、实例方法,只操作类属性、类方法。
- 装饰器:
@classmethod - 默认参数
cls,代表当前类本身。
class Demo: num = 10 @classmethod def test(cls): print(cls.num)3.6 静态方法
- 既不依赖实例对象,也不依赖类。
- 装饰器:
@staticmethod - 没有默认参数;一般是工具函数,为了封装放到类中。
class Demo: @staticmethod def tool(): print("静态方法")四、异常
4.1 异常捕获
- 使用
try...except捕获异常;代码报错不会直接终止程序,执行 except 内逻辑做异常处理。
4.2 捕获指定类型的异常
- 捕获多种异常:多个异常放到元组中。
try: pass except (ZeroDivisionError, NameError): pass- 写多个
except分别捕获不同异常。 Exception可以捕获绝大部分未知异常。
4.3 else 和 finally
else:try 代码块没有异常的时候执行。finally:无论是否发生异常,一定会执行,常用于资源释放。
try: pass except Exception: pass else: pass finally: pass4.4 自定义异常抛出
- 自定义异常类必须继承
Exception。 raise关键字主动抛出异常,可以抛出自定义异常或者系统异常。- raise 抛出的异常可以被 except 捕获,没有捕获则程序终止。
class MyErr(Exception): pass raise MyErr("自定义异常")五、Python 模块
- 模块:后缀为
.py的文件,可以存放变量、函数、类、可执行代码。
5.1 模块导入方式
# 1.导入整个模块 import os # 2.导入模块指定功能 from os import listdir, mkdir # 3.导入模块全部功能 from os import * # 4.别名导入 import os as xitong from os import listdir as ls5.2 自定义模块
- 模块名必须符合标识符命名规则。
- 导入模块时,会自动执行模块内部全部代码。
- 测试代码写在
if __name__ == '__main__':中,导入模块时不会执行测试代码。
if __name__ == '__main__': # 仅本文件直接运行执行 pass5.3 模块查询顺序
- 通过
sys.path查看模块搜索路径,列表靠前路径优先查找。 - 开发中手动追加路径:
sys.path.append("你的路径")。
5.4__all__
__all__ = ["func1","a"]- 只对
from 模块 import *生效,控制星号导入可以导入哪些内容。 import 模块名、from 模块 import a不受__all__控制。
5.5 包的导入
包:包含__init__.py文件的文件夹,用来管理多个模块。
# 导入包中指定模块 import 包名.模块名 # 从包导入模块 from 包名 import 模块名 # from 包名 import * # 需要在 __init__.py 文件配置 __all__ = ["模块名"]