PYTHON基础知识学习笔记(九)

对象持久化

对象持久化:将当前正在计算的数据结果或者状态永久存储存。

扁平文件

利用文本文件存储信息,首先将需要储存的变量转化为文本信息,再写入到文件中,使用时再将文本信息反序列化。
例:将列表存储到文本文件中再读取出来。

scores = [88, 99, 77, 55]              #需要存储的值

def write_scores():                    #写入文本文件
    with open('data_list.txt','w',encoding='utf8') as f:
        f.write(str(scores))
    print('文件写入完成...')    
    
if __name__ == '__main__':
    write_scores()

写入结果
在这里插入图片描述
data_list.txt文件
在这里插入图片描述
读取文件内容

def read_scores():                 
    with open('data_list.txt', 'r', encoding='utf8') as f:
        lst = f.read()
    print(lst)

if __name__ == '__main__':
    read_scores()

#运行结果
[88, 99, 77, 55]

读取出的结果看起来像列表,其实只字符串,不能进行列表操作。

def read_scores():
    with open('data_list.txt', 'r', encoding='utf8') as f:
        lst = f.read()
    lst[0] = 99
    print(lst)

if __name__ == '__main__':
    read_scores()

#运行结果
TypeError: 'str' object does not support item assignment

使用list()函数进行转换,会将字符串中每一个字符都转化为列表元素,包括符号。

def read_scores():
    with open('data_list.txt', 'r', encoding='utf8') as f:
        lst = f.read()
    print(list(lst))

if __name__ == '__main__':
    read_scores()

#运行结果
['[', '8', '8', ',', ' ', '9', '9', ',', ' ', '7', '7', ',', ' ', '5', '5', ']']

eval()函数可将文本文件中的内容直接转化为python语句。

def read_scores():
    with open('data_list.txt', 'r', encoding='utf8') as f:
        lst = eval(f.read())
    print(lst)
    lst[0] = 99
    print(lst)

if __name__ == '__main__':
    read_scores()

pickle

pickle模块实现了用于序列化和反序列化Python对象结构的二进制协议。“Pickling”是将Python对象层次结构转换为字节流的过程, “unpickling”是反向操作,从而将字节流(来自二进制文件或类似字节的对象)转换回对象层次结构。

序列化到字符串

1、pickle.dumps(obj) 将对象序列化为字符串。
2、pickle.loads(obj) 从字符串反序列化对象。

>>> import pickle
>>> person = {'name':'Tom','age':20}
>>> s = pickle.dumps(person)  #将一个字典表序列化为字节字符串
>>> s
b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x03\x00\x00\x00Tomq\x02X\x03\x00\x00\x00ageq\x03K\x14u.'
>>> p = pickle.loads(s)       #将字节字符串反序列化为原对象
>>> p
{'name': 'Tom', 'age': 20}
>>> type(p)                   #反序列化后的对象和之前的类型一样
dict

序列化到文件

1、pickle.dump(obj,file) 将对象序列化为文件。
2、pickle.load(file) 载入文件内容。

>>> import pickle
>>> person = {'name':'Tom','age':20}
>>> pickle.dump(person, open('pickle_db', 'wb'))

运行生成一个二进制文件pickle_db。
在这里插入图片描述
读取文件内容

>>> p = pickle.load(open('pickle_db', 'rb'))
>>> p
{'name': 'Tom', 'age': 20}
>>> type(p)
Out[12]: dict

shelve

当需要将多个变量储存到一个文件中时,可以使用shelve模块。
1、shelve.open(‘dbfile’) 创建数据库文件
2、db[‘key’] = obj 存储对象
3、len(db) 查看存储对象数量
4、del db[‘key’] 删除存储对象
5、db.close() 关闭当前文件

#创建一个名为shelve_student的二进制文件
import shelve
db = shelve.open('shelve_student')

将一个字典表及一个列表存储到刚才的文件中

>>> student = {'name': 'Tom', 'age': 20}
>>> scores = [99, 88, 77]
>>> db['s'] = student
>>> db['scores'] = scores

查看文件存储对象的个数

>>> len(db)
2

加载文件中存储的变量

#加载存储的字典表
>>> temp_student = db['s']
>>> temp_student
{'name': 'Tom', 'age': 20}
>>> type(temp_student)
dict
#加载存储的列表
>>> temp_scores = db['scores']
>>> temp_scores
[99, 88, 77]
>>> type(temp_scores )
list

可以删除文件中存储的对象

>>> del db['scores']         #删除对象scores
>>> len(db)                  #长度变为1
1
>>> db['s']                  #对象s依然存在
{'name': 'Tom', 'age': 20}  
>>> db['scores']             #加载对象scores会报错
Traceback (most recent call last):
  File "E:\software\anaconda3\azwj\lib\shelve.py", line 111, in __getitem__
    value = self.cache[key]
KeyError: 'scores'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "E:\software\anaconda3\azwj\lib\site-packages\IPython\core\interactiveshell.py", line 3331, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-32-76dcfbb20b51>", line 1, in <module>
    db['scores']
  File "E:\software\anaconda3\azwj\lib\shelve.py", line 113, in __getitem__
    f = BytesIO(self.dict[key.encode(self.keyencoding)])
  File "E:\software\anaconda3\azwj\lib\dbm\dumb.py", line 153, in __getitem__
    pos, siz = self._index[key]     # may raise KeyError
KeyError: b'scores'

将一个类实例存储到数据库文件

import shelve

class Student:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        return self.name

def write_shelve():
    s = Student('Tom', 20)
    db = shelve.open('shelve_student_db')
    db['s'] = s
    db.close()

if __name__ == '__main__':
    write_shelve()

运行后出现shelve_student_db文件
在这里插入图片描述
加载存储的实例

def read_shelve():
    db = shelve.open('shelve_student_db')
    st = db['s']
    print(st)
    print(st.name)
    print(st.age)
    db.close()

if __name__ == '__main__':
    read_shelve()

#运行结果
Tom
Tom
20

字符串本质

概述

1、类型
在Python3中字符串相关的类型有三种:
(1) str: 字符串
(2) bytes: 字节(不可变)
(3) bytearray: 字节数组(可变)
将字符变为字节的过程称为编码,将字节转为字符的过程称为解码。
2、字符编码架构
(1)字符集:赋值一个编码到某个字符,以便在内存中表示;
在这里插入图片描述
(2)编码Encoding:转换字符到原始字节形式;
(3)解码Decoding:依据编码名称转换原始字节为字符的过程。
3、字符串存储
(1)编码只作用于文件存储或中间媒介转换时;
(2)内存中总是存储解码以后的文本。

字符编码

一、ASCII
美国信息交换标准代码,基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。存储在一个字节(Byte), 0-127代码点。

>>> ord('A')     #获取字符代码点
65
>>> chr(104)     #获取代码点对应的字符
'h'

二、latin-1
超出ASCII包含的字母及符号,存储在一个Byte,128-255代码点。

>>> chr(202)
'Ê'
>>> ord('ß')
223

三、UTF-8
可变字节,相对通用,兼容ASCII。
(1)0-127 使用单字节
(2)128-2047 双字节存储
(3)>2047 3-4Byte
(4)每Byte使用 128-255

>>> ord('学')
23398
>>> chr(20249)
'伙'

四、UTF-16
2Byte存储字符(另加2Byte作为标识),兼容性高但内存占用大。
五、UTF-32
4Byte存储字符,兼容性高但内存占用大。

字节与文本的编码、解码

1、str.encode(‘编码’) 将特定字符编码

>>> s1 = 'ABCD'
>>> s1.encode('ASCII')
b'ABCD'    #前面带有吧,表示为字节码,而非字符串
>>> type(s1)
str
>>> type(s1.encode('ASCII'))
bytes
>>> s2 = '学习'
>>> s2.encode('UTF-8')
b'\xe5\xad\xa6\xe4\xb9\xa0'

编码器选择不当可能会报错,例如用ASCII对汉字编码。

>>> s2.encode('ASCII')
Traceback (most recent call last):
  File "E:\software\anaconda3\azwj\lib\site-packages\IPython\core\interactiveshell.py", line 3331, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-44-2aa70292e6ab>", line 1, in <module>
    s2.encode('ASCII')
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

使用不同的编码器,若不报错,则产生不同的字节码。

>>> s2.encode('UTF-16')
b'\xff\xfef[`N'
>>> s2.encode('UTF-32')
b'\xff\xfe\x00\x00f[\x00\x00`N\x00\x00'

2、bytes.decode(‘编码’) 将字符编码解码为字符文本

>>> b1 = b'\xe5\xad\xa6\xe4\xb9\xa0'
>>> b1.decode('utf-8')
'学习'

若编码与解码时使用的编码器不同,则会出现乱码或报错

>>> b1.decode('utf-16')
'귥\ue4a6ꂹ'

编码器可以不指定,默认使用UTF-8

>>> b1.decode()
'学习'

类型转换

1、字节bytes
(1)手动声明 :b’

>>> b = b'abc'
>>> type(b)
bytes

(2)字符串编码 str.encode()

>>> s = 'abc'
>>> s1 = '学习'
>>> s.encode()
b'abc'
>>> s1.encode()
b'\xe5\xad\xa6\xe4\xb9\xa0'

(3)构造函数 bytes()

>>> s = 'abc'
>>> s1 = '学习'
>>> bytes(s,'ascii')
b'abc'
>>> bytes(s1,'utf8')
b'\xe5\xad\xa6\xe4\xb9\xa0'

2、字节数组bytearray

(1)编码:bytearray(‘字符’,‘编码’)

>>> s1 = 'abc'
>>> ba = bytearray(s1,'utf8')
>>> ba
bytearray(b'abc')
>>> type(ba)
bytearray

字节数组是可变的

#更改元素
>>> ba[0]
97
>>> ba[0] = 98
>>> ba
bytearray(b'bbc')
#追加元素
>>> ba.append(212)
>>> ba
bytearray(b'bbc\xd4')
#当追加的字节超过编码器范围会报错
>>> ba.append(2122)
Traceback (most recent call last):
  File "E:\software\anaconda3\azwj\lib\site-packages\IPython\core\interactiveshell.py", line 3331, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-74-b57d1b0622e0>", line 1, in <module>
    ba.append(2122)
ValueError: byte must be in range(0, 256)

(2)解码为字符串 .decode()

>>> ba = bytearray('abc','utf8')
>>> ba.append(93)
>>> ba.decode('utf8')
'abc]'
>>> type(ba.decode('utf8'))
str

BOM处理

读取文件内容时可能会出现字节顺序标记,在指定解码器时加上“-sig”可以避免,如:open(‘data.txt’,‘r’,encoding=‘utf-8-sig’).read()。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值