设计模式---单例模式

简介

  单例模式(Singleton Pattern) 是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实
例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建
'''
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
'''
关键实现思想:
第一次创建类的对象的时候判断系统是否已经有这个单例,如果有则返回,如果没有则创建。那么后续再次
创建该类的实例的时候,因为已经创建过一次了,就不能再创建新的实例了,否则就不是单例啦,直接返回前
面返回的实例即可。

单例模式的python实现

使用“装饰器”来实现单例模式

  def Singleton(cls):  # 这是一个函数,目的是要实现一个“装饰器”,而且是对类型的装饰器
'''
cls:表示一个类名,即所要设计的单例类名称,
因为python一切皆对象,故而类名同样可以作为参数传递
'''
instance = {} def singleton(*args, **kargs):
if cls not in instance:
instance[cls] = cls(*args, **kargs) # 如果没有cls这个类,则创建,并且将这个cls所创建的实例,保存在一个字典中
return instance[cls] return singleton @Singleton
class Student(object):
def __init__(self, name, age):
self.name = name
self.age = age s1 = Student('张三', 23)
s2 = Student('李四', 24)
print((s1 == s2))
print(s1 is s2)
print(id(s1), id(s2), sep=' ') 运行结果:
True
True
24171496 24171496

通过__new__函数去实现

  若要得到当前类的实例,应在当前类__new__()中调用其父类的__new__()来返回,python2和python3调
用父类的__new__()方法不同:
python2: object.__new__(cls)
python3: super().__new__(cls) #super()中类可加可不加
'''基于python3代码:'''
class Student(object):
instance = None def __new__(cls, name, age):
if not cls.instance:
cls.instance = super(Student, cls).__new__(cls)
return cls.instance def __init__(self, name, age):
self.name = name
self.age = age s1 = Student('张三', 23)
s2 = Student('李四', 24)
print((s1 == s2))
print(s1 is s2)
print(id(s1), id(s2), sep=' ') 运行结果:
True
True
27579152 27579152 '''基于python2代码实现:'''
if not cls.instance:
cls.instance = object.__new__(cls)
return cls.instance

使用一个单独的模块作为单例模式

  因为,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入
时,就会直接加载 .pyc 文件,而不会再次执行模块代码。
因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做: 在一个模块中定义一个普通的类,如在demo.py模块中定义如下代码
#demo.py
class Student:
def __init__(self,name,age):
self.name=name
self.age=age student=Student('张三',23) 这里的student就是一个单例。 当我们在另外一个模块中导入student这个对象时,因为它只被导入了一
次,所以总是同一个实例。
#test.py
from demo import student
#此时,无论该test脚本怎么运行,import进来的student实例是唯一的

pickle模块

pickle模块的介绍

  (1)pickle模块:

         pickle模块是python语言的一个系统内置模块,安装python后已包含pickle库,不需要单独再安装。

  (2)pickle模块的特点:

        1、只能在python中使用,只支持python的基本数据类型,是python独有的模块。

        2、序列化的时候,只是序列化了整个序列对象,而不是内存地址。

        3、pickle有两类主要的接口,即序列化和反序列化;

       通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储;

       通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象。

(3)为什么需要序列化和反序列化操作呢?

      1、便于存储

  序列化过程是将Python程序运行中得到了一些字符串、列表、字典等数据信息转变为二进制数据流。这样信息
就容易存储在硬盘之中,当需要读取文件的时候,从硬盘中读取数据,然后再将其反序列化便可以得到原始的数据。 2、便于传输 当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的
形式在网络上传送。发送方需要把对象转换为字节序列,在网络上传输;接收方则需要把字节序列在恢复为
对象,得到原始的数据。

pickle模块的使用

序列化操作

  序列化方法1:pickle.dump()
格式为:pickle.dump(obj,file)
该方法是将序列化后的对象obj以二进制形式写入文件file中,进行保存,不能直接预览。 关于文件file,
必须是以二进制的形式进行操作(写入)。 示例如下:将五个学生的成绩写入到成绩表中,保存在cjb.txt文件中
import random
import pickle # 初始化成绩表为空
cjb = [] # 写入5个学生的数据到成绩表中
for i in range(5):
name = input("name:") # 姓名
cj = random.randint(50, 100) # 随机生成50——100之间的整数作为成绩
cjb.append([name, cj])
print(cjb) # 将成绩表中的数据保存到cjb.txt文件中
with open('cjb.txt', 'wb') as f:
pickle.dump(cjb, f)
print("结果已保存")
  序列化方法2:pickle.dumps()
格式为:pickle.dumps(obj)
pickle.dumps()方法跟pickle.dump()方法不同:pickle.dumps()方法不需要写入文件中,而是
直接返回一个序列化的bytes对象。
示例如下:与上面的例子一样,只是方法不同,将五个学生的成绩写入到成绩表中,保存在cjb.txt文件中 import random
import pickle #初始化成绩表为空
cjb=[] #写入5个学生的数据到成绩表中
for i in range(5):
name=input("name:") #姓名
cj=random.randint(50,100) #成绩
cjb.append([name,cj])
print(cjb)
print(pickle.dumps(cjb)) #序列化的bytes对象
print(type(pickle.dumps(cjb))) #class 'bytes' #将成绩表中的数据保存到cjb.txt文件中
with open('cjb.txt','wb')as f:
f.write(pickle.dumps(cjb))
print("结果已保存") 运行结果为:
[['1', 66], ['2', 70], ['3', 58], ['4', 96], ['5', 63]]
b'\x80\x04\x957\x00\x00\x00\x00\x00\x00\x00]\x94(]\x94(\x8c\x011\x94KBe]\x94(\x8c\x012\x94KFe]\x94(\x8c\x013\x94K:e]\x94(\x8c\x014\x94K`e]\x94(\x8c\x015\x94K?ee.'
<class 'bytes'>
结果已保存

反序列化操作

  反序列化方法1:pickle.load()
该方法是将序列化的对象从文件file中读取出来。关于文件file,必须是以二进制的形式进行操作(读取)。
示例如下:与上面的例子一样,将五个学生的成绩写入到成绩表中,保存在cjb.txt文件中;再次运行程序
时,读取cjb.txt中的学生信息,进行加载,再次写入数据时,以追加的方式写入。
import random
import pickle #如果没有cjb,就让cjb=[],如果存在,就将内容读取出来
try:
with open('cjb.txt','rb')as f:
cjb=pickle.load(f)
print(cjb)
print("结果已加载")
except:
cjb=[]
#写入5个学生的数据到成绩表中
for i in range(5):
name=input("name:") #姓名
cj=random.randint(50,100) #成绩
cjb.append([name,cj])
print(cjb) #将成绩表中的数据保存到cjb.txt文件中
with open('cjb.txt','wb')as f:
pickle.dump(cjb,f)
print("结果已保存")
运行结果:
[['1', 66], ['2', 70], ['3', 58], ['4', 96], ['5', 63]]
结果已加载
name:11
name:22
name:33
name:44
name:55
[['1', 66], ['2', 70], ['3', 58], ['4', 96], ['5', 63], ['11', 97], ['22', 87], ['33', 50], ['44', 98], ['55', 89]]
结果已保存
  反序列化方法2:pickle.loads()
格式为:pickle.loads()
pickle.loads()方法跟pickle.load()方法不同:pickle.loads()方法是直接从bytes对象中读取
序列化的信息,而非从文件中读取。下面的例子是将信息保存到了文件中,所以要从文件中读取,以
pickle.loads(f.read())的方式读取。 示例如下:与上面的例子一样,将五个学生的成绩写入到成绩表中,保存在cjb.txt文件中;再次运行程序
时,读取cjb.txt中的学生信息,进行加载,再次写入数据时,以追加的方式写入。
import random
import pickle #如果没有cjb,就让cjb=[],如果存在,就将内容读取出来
try:
with open('cjb.txt','rb')as f:
cjb=pickle.loads(f.read())
print(cjb)
print("结果已加载")
except:
cjb=[] #写入5个学生的数据到成绩表中
for i in range(5):
name=input("name:") #姓名
cj=random.randint(50,100) #成绩
cjb.append([name,cj])
print(cjb) #将成绩表中的数据保存到cjb.txt文件中
with open('cjb.txt','wb')as f:
f.write(pickle.dumps(cjb))
print("结果已保存") 运行结果:
[['1', 87], ['2', 59], ['3', 78], ['4', 77], ['5', 75]]
结果已加载
name:a
name:b
name:c
name:d
name:e
[['1', 87], ['2', 59], ['3', 78], ['4', 77], ['5', 75], ['a', 55], ['b', 86], ['c', 86], ['d', 61], ['e', 67]]
结果已保存

选课系统项目分析

需求分析

选课系统
角色:学校、学员、课程、讲师
要求:
1. 创建北京、上海 2 所学校
2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开
3. 课程包含,周期,价格,通过学校创建课程
4. 通过学校创建班级, 班级关联课程、讲师
5. 创建学员时,选择学校,关联班级
5. 创建讲师角色时要关联学校,
6. 提供三个角色接口
6.1 学员视图, 可以登录,注册, 选择学校,选择课程,查看成绩
6.2 讲师视图, 讲师登录,选择学校,选择课程, 查看课程下学员列表 , 修改所管理的学员的成绩
6.3 管理视图,登录,注册,创建讲师, 创建班级,创建课程,创建学校
7. 上面的操作产生的数据都通过pickle序列化保存到文件里

设计分析

表示层:(向用户显示对应视图的功能)
管理员视图
学生视图
讲师视图 业务逻辑层:(主要实现功能的代码)
管理员业务:登录,注册,创建讲师, 创建班级,创建课程,创建学校
学生业务:登录,注册, 选择学校,选择课程,查看成绩
讲师业务:讲师登录,选择学校,选择课程, 查看课程下学员列表 , 修改所管理的学员的成绩 数据访问层:(对数据库的存储和取出)
存储数据

设计模式---单例模式,pickle模块的更多相关文章

  1. JavaScript设计模式-单例模式、模块模式(转载 学习中。。。。)

    (转载地址:http://technicolor.iteye.com/blog/1409656) 之前在<JavaScript小特性-面向对象>里面介绍过JavaScript面向对象的特性 ...

  2. 单例模式与pickle模块

    目录 设计模式之单例模式 pickle模块 设计模式之单例模式 设计模式是前辈们发明的经过反复验证用于解决固定问题的固定套路,在IT行业中设计模式总共有23种,可以分为三大类:创建型.结构型.行为型. ...

  3. python_way,day8 面向对象【多态、成员--字段 方法 属性、成员修饰符、特殊成员、异常处理、设计模式之单例模式、模块:isinstance、issubclass】

    python_way day8 一.面向对象三大特性: 多态 二.面向对象中的成员 字段.方法属性 三.成员修饰符 四.特殊成员 __init__.__doc__.__call__.__setitem ...

  4. Java设计模式の单例模式

    -------------------------------------------------- 目录 1.定义 2.常见的集中单例实现 a.饿汉式,线程安全 但效率比较低 b.单例模式的实现:饱 ...

  5. python模块(json和pickle模块)

    json和pickle模块,两个都是用于序列化的模块 • json模块,用于字符串与python数据类型之间的转换 • pickle模块,用于python特有类型与python数据类型之间的转换 两个 ...

  6. 【python】pickle模块

    持久性的基本思想很简单.假定有一个 Python 程序,它可能是一个管理日常待办事项的程序,您希望在多次执行这个程序之间可以保存应用程序对象(待办事项).换句话说,您希望将对象存储在磁盘上,便于以后检 ...

  7. python数据持久存储:pickle模块的基本使用

    经常遇到在Python程序运行中得到了一些字符串.列表.字典等数据,想要长久的保存下来,方便以后使用,而不是简单的放入内存中关机断电就丢失数据. 这个时候Pickle模块就派上用场了,它可以将对象转换 ...

  8. python数据持久存储:pickle模块的使用

    python的pickle模块实现了基本的数据序列和反序列化.通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储:通过pickle模块的反序列化操作,我们能够从文件 ...

  9. Python(正则 Time datatime os sys random json pickle模块)

    正则表达式: import re #导入模块名 p = re.compile(-]代表匹配0至9的任意一个数字, 所以这里的意思是对传进来的字符串进行匹配,如果这个字符串的开头第一个字符是数字,就代表 ...

随机推荐

  1. SQLyog创建用户并授权的过程

    点击你要授权的数据库然后点击用户管理器 然后输入用户名和密码主机选localhost 然后点击创建,然后选择你创建的数据库全选 最后保存就可以了

  2. 指出在 spring aop 中 concern 和 cross-cutting concern 的不同之处?

    concern 是我们想要在应用程序的特定模块中定义的行为.它可以定义为我们想 要实现的功能. cross-cutting concern 是一个适用于整个应用的行为,这会影响整个应用程序. 例如,日 ...

  3. vmware克隆Centos虚拟机网卡无法启动问题

    快速处理办法: cat /etc/sysconfig/network-scripts/ifcfg-eth0 sed -i '/UUID/d' /etc/sysconfig/network-script ...

  4. 算法导论 - 基础知识 - 算法基础(插入排序&归并排序)

    在<算法导论>一书中,插入排序作为一个例子是第一个出现在该书中的算法. 插入排序: 对于少量元素的排序,它是一个有效的算法. 插入排序的工作方式像许多人排序一手扑克牌.开始时,我们手中牌为 ...

  5. 如何在 Microsoft word中插入代码

    一.工具 方法1.打开这个网页PlanetB; 方法2.或者谷歌搜索syntax highlight code in word documents,检索结果的第一个.如下图: PS. 方法1和2打开的 ...

  6. 《CSS世界》笔记二:盒模型四大家族

    上一篇:<CSS世界>笔记一:流/元素/尺寸下一篇:<CSS世界>笔记三:内联元素与对齐 写在前面 在读<CSS世界>第四章之前,粗浅的认为盒模型无非是margin ...

  7. ES6-11学习笔记--let

    新声明方式:let 1.不属于顶层对象 window 2.不允许重复声明 3.不存在变量提升 4.暂时性死区 5.块级作用域   原来var声明: var a = 5; console.log(a); ...

  8. C++:Abstract class : invalid abstract return type for member function ‘virtual...’

    #include <iostream> #include <cmath> #include <sstream> using namespace std; class ...

  9. Pascal的旅行

    [问题描述] 一块的nxn游戏板上填充着整数,每个方格上为一个非负整数.目标是沿着从左上角到右下角的任何合法路径行进,方格中的整数决定离开该位置的距离有多大,所有步骤必须向右或向下.请注意,0是一个死 ...

  10. 解决PHP下载大文件失败,并限制下载速度

    1.问题: PHP在使用readfile函数定义下载文件时候,文件不可以过大,否则会下载失败,文件损坏且不报错: 2.原因: 这个是因为readfile读取文件的时候会把文件放入缓存,导致内存溢出: ...