0
点赞
收藏
分享

微信扫一扫

14Python单例与异常


单例

  • 单例设计模式
  • 目的 —— 让 创建的对象,在系统中 只有 唯一的一个实例
  • 每一次执行 ​​类名()​​ 返回的对象,内存地址是相同的

__new__ 方法

  • 使用 类名() 创建对象时,​​Python​​ 的解释器 首先 会 调用 ​​__new__​​ 方法为对象 分配空间
  • ​__new__​​是一个由object基类提供的内置的静态方法,主要作用有两个:
  • 在内存中为对象 分配空间
  • 返回 对象的引用
  • ​Python​​ 的解释器获得对象的 引用 后,将引用作为 第一个参数,传递给 ​​__init__​​ 方法

重写 ​​__new__​​ 方法 的代码非常固定!

  • 重写 ​​__new__​​ 方法 一定要​return super().__new__(cls)​
  • 否则 Python 的解释器 得不到 分配了空间的 对象引用就不会调用对象的初始化方法
  • 注意:​​__new__​​ 是一个静态方法,在调用时需要 主动传递​cls​​ 参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RJrsaV5v-1671796318240)(14单例与异常.assets/image-20221223195116841.png)]

class MusicPlayer(object):

def __new__(cls, *args, **kwargs):
# 如果不返回任何结果,
return super().__new__(cls)

def __init__(self):
print("初始化音乐播放对象")

player = MusicPlayer()

print(player)

单例

  • 单例—— 让 类 创建的对象,在系统中 只有唯一的一个实例
  1. 定义一个 类属性,初始值是 ​​None​​,用于记录 单例对象的引用
  2. 重写 ​​__new__​​ 方法
  3. 如果 类属性​is None​​,调用父类方法分配空间,并在类属性中记录结果
  4. 返回 类属性 中记录的 对象引用

class MusicPlayer(object):

# 定义类属性记录单例对象引用
instance = None

def __new__(cls, *args, **kwargs):

# 1. 判断类属性是否已经被赋值
if cls.instance is None:
cls.instance = super().__new__(cls)

# 2. 返回类属性的单例引用
return cls.instance

只执行一次初始化工作

  • 在每次使用​​类名()​​创建对象时,Python的解释器都会自动调用两个方法:
  • ​__new__​​ 分配空间
  • ​__init__​​ 对象初始化
  • 在上一小节对 ​​__new__​​ 方法改造之后,每次都会得到 第一次被创建对象的引用
  • 但是:初始化方法还会被再次调用

需求

  • 初始化动作 只被 执行一次

class MusicPlayer(object):

# 记录第一个被创建对象的引用
instance = None
# 记录是否执行过初始化动作
init_flag = False

def __new__(cls, *args, **kwargs):

# 1. 判断类属性是否是空对象
if cls.instance is None:
# 2. 调用父类的方法,为第一个对象分配空间
cls.instance = super().__new__(cls)

# 3. 返回类属性保存的对象引用
return cls.instance

def __init__(self):

if not MusicPlayer.init_flag:
print("初始化音乐播放器")

MusicPlayer.init_flag = True


# 创建多个对象
player1 = MusicPlayer()
print(player1)

player2 = MusicPlayer()
print(player2)

异常

异常的概念

  • 程序在运行时,如果 ​​Python 解释器​遇到 到一个错误,会停止程序的执行,并且提示一些错误信息,这就是 异常
  • 程序停止执行并且提示错误信息 这个动作,我们通常称之为:抛出(raise)异常

程序开发时,很难将 所有的特殊情况 都处理的面面俱到,通过 异常捕获 可以针对突发事件做集中的处理,从而保证程序的 稳定性和健壮性

捕获异常

  • 在程序开发中,如果 对某些代码的执行不能确定是否正确,可以增加 ​​try(尝试)​​ 来 捕获异常
  • 捕获异常最简单的语法格式:

try:
尝试执行的代码
except:
出现错误的处理

  • ​try​尝试,下方编写要尝试代码,不确定是否能够正常执行的代码
  • ​except​如果不是,下方编写尝试失败的代码

错误类型捕获

  • 在程序执行时,可能会遇到 不同类型的异常,并且需要 针对不同类型的异常,做出不同的响应,这个时候,就需要捕获错误类型了
  • 语法如下:

try:
# 尝试执行的代码
pass
except 错误类型1:
# 针对错误类型1,对应的代码处理
pass
except (错误类型2, 错误类型3):
# 针对错误类型2 和 3,对应的代码处理
pass
except Exception as result:
print("未知错误 %s" % result)

案例:除零异常

try:
num = int(input("请输入整数:"))
result = 8 / num
print(result)
except ValueError:
print("请输入正确的整数")
except ZeroDivisionError:
print("除 0 错误")

异常捕获完整语法

try:
# 尝试执行的代码
pass
except 错误类型1:
# 针对错误类型1,对应的代码处理
pass
except 错误类型2:
# 针对错误类型2,对应的代码处理
pass
except (错误类型3, 错误类型4):
# 针对错误类型3 和 4,对应的代码处理
pass
except Exception as result:
# 打印错误信息
print(result)
else:
# 没有异常才会执行的代码
pass
finally:
# 无论是否有异常,都会执行的代码
print("无论是否有异常,都会执行的代码")

异常的传递

  • 异常的传递 —— 当 函数/方法 执行 出现异常,会 将异常传递 给 函数/方法 的 调用一方
  • 如果 传递到主程序,仍然 没有异常处理,程序才会被终止

抛出 ​​raise​​ 异常

  • 在开发中,除了 代码执行出错​Python​​ 解释器会 抛出 异常之外
  • 还可以根据 应用程序 特有的业务需求 主动抛出异常
  • ​Python​​​ 中提供了一个 ​​Exception​异常类
  • 在开发时,如果满足特定业务需求时,希望 抛出异常,可以:
  1. 创建 一个 ​​Exception​​ 的 对象
  2. 使用 ​​raise​关键字 抛出 异常对象

def input_password():

# 1. 提示用户输入密码
pwd = input("请输入密码:")

# 2. 判断密码长度,如果长度 >= 8,返回用户输入的密码
if len(pwd) >= 8:
return pwd

# 3. 密码长度不够,需要抛出异常
# 1> 创建异常对象 - 使用异常的错误信息字符串作为参数
ex = Exception("密码长度不够")

# 2> 抛出异常对象
raise ex


try:
user_pwd = input_password()
print(user_pwd)
except Exception as result:
print("发现错误:%s" % result)


举报

相关推荐

0 条评论