单例
设计模式:前人留下的对某一特定问题的成熟的解决方案(套路)
单例设计模式:类创建的对象,在系统中只有唯一一个实例,每一次执行类名()返回的对象,内存地址是相同的
__new__方法:
使用类名()创建对象时,python解释器执行两步:
1首先调用__new__内置方法为对象分配空间,返回对象的引用(地址)
2调用__init__内置方法进行对象初始化
class MusicPlayer(object):
pass
# 创建多个对象
player1 = MusicPlayer()
print(player1)
player2 = MusicPlayer()
print(player2)
<__main__.MusicPlayer object at 0x10126a4a8>
<__main__.MusicPlayer object at 0x10126a470>
输出的两个内存地址不一样,说明player1和player2是两个完全不同的对象
单例设计模式的目的就是无论创建多少次,对象的引用(地址)是相同的,怎么解决?
定义一个类属性instance,初始值是None,用于记录对象的引用(初始时没有值)
class MusicPlayer(object):
# 定义类属性,记录第一个被创建对象的引用
instance = None
def __new__(cls, *args, **kwargs):
# 1 判断类属性是否是空对象
if cls.instance is None:
# 2 调用父类的方法,为第一个对象分配空间
cls.instance = super().__new__(cls)
# 3 返回类属性保存的对象引用
return cls.instance
# 创建多个对象
player1 = MusicPlayer()
print(player1)
player2 = MusicPlayer()
print(player2)
<__main__.MusicPlayer object at 0x1049c5438>
<__main__.MusicPlayer object at 0x1049c5438>
如果想要初始化动作只执行一次?
定义类属性,判断是否执行过初始化
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):
# 1 判断是否执行过初始化动作
if MusicPlayer.init_flag:
return
# 2 如果没有执行过
print("初始化")
# 3 修改类属性的标记
MusicPlayer.init_flag = True
# 创建多个对象
player1 = MusicPlayer()
print(player1)
player2 = MusicPlayer()
print(player2)
异常
程序在运行时,遇到错误停止运行并提示一些错误信息
通过异常捕获,保证程序的健壮性
在程序的开发中,如果对某些代码的执行不确定是否正确,可以增加try来捕获异常
格式:
try:
尝试执行的代码
except:
出现错误的处理
try:
num = int(input("请输入一个整数:"))
except:
print("请输入正确的整数")
print("-" * 50)
请输入一个整数:eee
请输入正确的整数
--------------------------------------------------
异常类型捕获演练:
输入一个非零整数,进行除以8的操作,
错误类型:
try:
num = int(input("请输入一个整数:"))
result = 8 / num
print(result)
except ZeroDivisionError:
print("除0错误")
except ValueError:
print("请输入正确的整数")
以上捕获的错误类型都是已知的错误,如果想对未知的错误进行捕获?
可以再增加一个except
try:
num = int(input("请输入一个整数:"))
result = 8 / num
print(result)
except ZeroDivisionError:
print("除0错误")
#假设输入非整数时为未知错误
except Exception as result:
print("未知错误%s" % result)
请输入一个整数:a
未知错误invalid literal for int() with base 10: 'a'
异常捕获完整语法
try:
num = int(input("请输入一个整数:"))
result = 8 / num
print(result)
except ZeroDivisionError:
print("除0错误")
except ValueError:
print("请输入正确的整数")
except Exception as result:
print("未知错误%s" % result)
else:
print("尝试成功")
finally:
print("无论是否出现错误都会执行的代码")
异常的传递:
把异常传递给函数或方法的调用方,程序不会被立刻终止
例:定义函数demo1()提示用户输入一个整数并返回;定义函数demo2()调用demo1();在主程序中使用demo2()
def demo1():
return int(input("输入整数:"))
def demo2():
return demo1()
# 利用异常的传递性,在主程序捕获异常
try:
print(demo2())
except Exception as result:
print("位置错误 %s" % result)
运行结果
输入整数:a
位置错误 invalid literal for int() with base 10: 'a'
注:
在开发中,在主函数中添加异常捕获
在主函数中调用的其他函数,只要出现异常,都会传递到主函数的异常捕获中
这样就不需要在代码中,增加大量的异常捕获,能够保证代码的整洁性
在实际开发中,除了代码出错需要抛出异常,还可以根据应用程序特有的业务需求主动抛出异常:
1.创建exception异常对象
2.使用raise关键字抛出异常对象
例,提示用户输入密码,如果长度少于8,抛出异常
def input_password():
# 1.输入密码
pwd = input("请输入密码")
# 2.判断长度>=8,返回用户输入的密码
if len(pwd) >= 8:
return
# 3.如果<8主动抛出异常
print("主动抛出异常")
ex = Exception("密码长度不够")
raise ex
try:
print(input_password())
except Exception as result:
print(result)