6. 小数据池-编码-文件操作

一、小数据池

1. 小数据池定义

小数据池(常量池),一种数据缓存机制,也被称为驻留机制。小数据池只针对:整数、字符串、布尔值。其他数据类型不存在驻留机制。

2. 各类型数据池限定

(1) 整型

在python中 -5 ~ 256 之间的整数会被驻留在内存中。每次使用都是同一个对象。

(2) 字符串

将一定规则的字符串缓存。在使用的时候,内存中只会创建一个该数据的对象。保存在小数据池中。当使用的时候直接从小数据池中获取对象的内存应用。而不需要创建一个新的数据,这样会节省更多的内存区域。

优点:能提高一些字符串,整数的处理速度。省略创建对象的过程

缺点:在“池”中创建或插入新的内容会花费更多的时间

a. 如果字符串的长度是0或者1, 都会默认进行缓存 
b. 字符串长度大于1, 但是字符串中只包含字母, 数字, 下划线时才会缓存
c. 用乘法得到的字符串.
	①. 乘数为1, 仅包含数字, 字母, 下划线时会被缓存. 如果包含其他字符, 而长度<=1 也会被驻存, 
    ②. 乘数大于1 . 仅包含数字, 字母, 下划 线这个时候会被缓存. 但字符串长度不能大于20 
d. 指定驻留留. 我们可以通过sys模块中的intern()函数来指定要驻留留的内容.

>>> from sys import intern
>>> a = intern('alex.sb.com' * 10)
>>> b = intern('alex.sb.com' * 10)
>>> a is b
True

3. py文件与command小数据池区别

​ 在代码块内的缓存机制是不一样的. 在执行同一个代码块的初始化对象的命令时, 会检查其值是否已经存在, 如果存在, 会将其重用. 换句话说: 执行同一个代码块时, 遇到初始 化对象的命令时,他会将初始化的这个变量与 值存储在一个字典中, 在遇到新的变量时, 会先在字典中查询记录, 如果有同样的记录那么它会重复使用这个字典中的之前的这个值. 所以在 你给出的例子中, 文件执行时(同一个代码块) 会把a, b两个变量指向同一个对象. 如 果是不同的代码块, 他就会看这个两个变量是否是满足小数据池的数据, 如果是满足小数据池的数据则会指向同一个地址. 所以: a, b的赋值语句分别被当作两个代码块执行, 但是他们不满足小数据池的数据所以会得到两个不同的对象, 因而is判断返回False.

​ py文件里. 一个代码块内部. 只会缓存int, str, bool 也有自己的小数据池。 缓存的范围会比外面的代码块的数据池要大

​ (1). 数字。都会缓存。 运算的结果不缓存(-5~256 会缓存)

​ (2). 字符串。 默认的字符串都缓存. 如果有乘法。 遵循上方的结论

​ (3). 布尔值。 默认缓存

4. is 和 == 区别

查看内存地址:id(变量)   

is : 判断左右两端内容的内存地址是否一致. 如果返回True, 那可以确定这两个变量量使 用的是同一个对象
== :判断左右两端的值是否相等. 是不是一致.

二、编码

1. python2和python编码

(1) python2 - ASCII

默认使用ASCII码,所以不支持中文. 如果需要在Python2中更改编码. 需要在文件的开始编写。

# -- encoding:utf-8 -
(2) python3 - UTF-8
(1)ASCII : 最早的编码.里面有英文大写字母,小写字母,数字,一些特殊字符.没有中文,8个01代码,8b,1B  (2)GBK: 中文国标码,里面包含了ASCII编码和中文常用编码.16b, 2B
(3)UNICODE: 万国码, 里面包含了全世界所有国家文字的编码. 32b, 4B, 包含了了 ASCII
(4)UTF-8: 可变长度的万国码.是unicode的一种实现.最⼩字符占8位;
          英文8b,1B  欧文16b,2B  中文24bit,3B
	      综上, 除了了ASCII码以外, 其他信息不能直接转换.

2. 编解码

​ 在python3的内存中。 在程序运⾏阶段。 使用的是unicode编码。 因为unicode是万国码。 什么内容都可以进行显示。 那么在数据传输和存储的时候由于unicode比较浪费空间和资源。 需要把 unicode转存成UTF-8或者GBK 进行存储。 怎么转换呢。 在python中可以把文字信息进行编码。 编码之后的内容就可以进行传输了。 编码之后的数据是bytes类型的数据。其实啊。 还是原来的数据只是经过编码之后表现形式发生了改变而已。

​ bytes的表现形式: (1)英⽂ b'alex' 英⽂的表现形式和字符串没什么两样 (2)中文 b'xe4xb8xad' 这是一个汉字的UTF-8的bytes表现形式

(1) 举例
s = "alex"
print(s.encode("utf-8"))    # 将字符串串编码成UTF-8
print(s.encode("GBK"))  # 将字符串串编码成GBK
结果:
b'alex'
b'alex'
s = "中"
print(s.encode("UTF-8"))    # 中?文编码成UTF-8
print(s.encode("GBK"))  # 中?文编码成GBK
结果:
b'xe4xb8xad'
b'xd6xd0

备注:英⽂编码之后的结果和源字符串一致.中文编码之后的结果根据编码的不同. 编码结果也不同. 我们能看到. 一个中文的UTF-8编码是3个字节. 一个GBK的中文编码是2个字节. 编码之后的类型就是bytes类型.在网络传输和存储的时候我们python是保存和存储的bytes 类型. 那么在对方接收的时候. 也是接收的bytes类型的数据. 我们可以使用decode()来进行解码操作. 把bytes类型的数据还原回我们熟悉的字符串

s = "我叫李李嘉诚" 
print(s.encode("utf-8"))    
# b'xe6x88x91xe5x8fxabxe6x9dx8exe5x98x89xe8xafx9a' 
# 解码
print(b'xe6x88x91xe5x8fxabxe6x9dx8exe5x98x89xe8xafx9a'.decod e("utf-8"))  
s = "我是文字" 
bs = s.encode("GBK")    # 我们这样可以获取到GBK的文字 
# 把GBK转换成UTF-8 
# 首先要把GBK转换成unicode. 也就是需要解码 
s = bs.decode("GBK")  # 解码 
# 然后需要进行重新编码成UTF-8 
bss = s.encode("UTF-8") # 重新编码 
print(bss)

三、文件操作

1. 初始文件操作

​ 使用python来读写文件时非常简单的操作。我们使用open()函数来打开一个文件,获取文件句柄,然后通过文件句柄就可以进行各种文件操作。打开文件需要close()文件。可使用with上下文进行操作文件。

2. 文件操作模式

​ 文件操作流程:建立文件对象,调用文件方法进行操作,不要忘记关闭文件(文件不关闭的情况下,内容会放在缓存,虽然python会在最后自动把内容读到磁盘)

(1) r(only-read)
f = open("file", "r")
# read逐个字符地全部读取出,read可以指定参数,设定要读取多少字符;无论一个英文字母还是一个汉字都是一个字符
f_read = f.read()
f = open('file1','r')
# readlines会把内容以列表的形式输出
f_read = f.readlines() 
print(f_read)
f.close()
# 推荐读取方式

#输出一行内容输出一个空行,一行内容一行空格... 因为文件中每行内容后面都有一个换行符,而且print()语句本身就可以换行,如果不想输出空行,就需要使用下面的语句:print(line.strip())
f = open('file1','r')
for line in f.readlines() 
  print(line) 
f.close()
# 读取图片、视频流文件 - rb
f = open('file', rb)
(2) w(only-write)

​ 在进行操作前,文件中所有内容会被清空。由于Python3的默认编码方式是Unicode,所以在写入文件的时候需要调用utf8,以utf8的方式保存,这时pycharm(默认编码方式是utf8)才能正确读取,当读取文件时,文件是utf8格式,pycharm也是utf8,就不需要调用了。写入字节文件wb

f = open('file1','w',encoding='utf8')  
f_w = f.write('hello world')
#有意思的是,这里并不打印'hello world',只打印写入多少字符
print(f_w)  
f.close()
(3) a(append)

​ 与w模式不同的是,a模式不会把原来内容清空,而是光标移到内容最后位置,继续写入新内容。比如在最后追加'hello world'

f = open('file1','a')
f_a = f.write('hello world')
#还是会打印写入的字符数
print(f_a) 
f.close()
(4) 读取大文件
num = 0
# 不要过早关闭文件,否则程序不能识别操作句柄f.
f.close() 
f = open('file','r')
# for内部把f变为一个迭代器,用一行取一行
for i in f:  
  num += 1
  if num == 5:
    i = ''.join([i.strip(),'hello world'])
  print(i.strip())
f.close()

3. 其他操作

(1) tell 和 seek
f = open('file','r')
print(f.tell())  #光标默认在起始位置
f.seek(10)    #把光标定位到第10个字符之后
print(f.tell())  #输出10
f.close()
----------------------
f = open('file','w')
print(f.tell())  #先清空内容,光标回到0位置
f.seek(10)    
print(f.tell())
f.close()
----------------------
f = open('file','a')
print(f.tell())  #光标默认在最后位置
f.write('你好 世界')
print(f.tell())  #光标向后9个字符,仍在最后位置
f.close()
(2) flush

​ 同步将数据从缓存转移到磁盘; 如实现进度条

import sys,time  #导入sys和time模块
for i in range(40):
  sys.stdout.write('*')
  # flush的作用相当于照相,拍一张冲洗一张
  sys.stdout.flush()  
  time.sleep(0.2)

# 下面代码也能够实现相同的功能
import time 
for i in range(40):
  # print中的flush参数
  print('*',end='',flush=True) 
  time.sleep(0.2)
(3) truncate - 截断

不能是r模式下执行,w模式下,已经清空所有数据,使用truncate没有任何意义,a模式下,截断指定位置后的内容。

f = open('file','a')
# 只显示6个字节的内容(6个英文字符或三个汉字),后面的内容被清空
f.truncate(6) 
(4) 光标位置总结
#--------------------------光标总结head-----------------------------------
f = open('file','r')
print(f.read(6)) #6个字符
print(f.tell())  #位置12字节,一个汉字两个字节
f.close()
 
f = open('file','r')
f.seek(6)      #6个字节
print(f.tell())
f.close()
 
f = open('file','a')
# 光标默认在最后位置
print(f.tell())  
f.write('你好 世界')
# 光标向后9个字节,一个汉字两个字节,仍在最后位置 182-->191
print(f.tell())  
f.close()
 
f = open('file','a',encoding='utf-8')
# 由于需要光标定位位置,所以也是字节。只显示6个字节的内容(6个英文字母或三个汉字,一个汉字两个字节),后面的内容被清空。
print(f.truncate(6)) 
f.close()
(4) r+/w+/a+

​ r+:读写模式,光标默认在起始位置,当需要写入的时候,光标自动移到最后

​ w+:写读模式,先清空原内容,再写入,也能够读取

​ a+:追加读模式,光标默认在最后位置,直接写入,也能够读取。

f = open('file','a')
print(f.tell())  #末尾207位置
f.close()
 
f = open('file','r+')
print(f.tell())  #0位置
print(f.readline()) #读取第一行
f.write('羊小羚')   #光标移到末尾207位置并写入
print(f.tell())  #213位置
f.seek(0)     #光标移到0位置
print(f.readline())  #读取第一行
f.close()
(5) 修改文件内容
由于数据存储机制的关系,我们只能把文件1中的内容读取出来,经过修改后,放到文件2中

f2 = open('file2','w',encoding='utf8')  #写入的时候必须加utf8
f1 = open('file','r')
num = 0
for line in f1: #迭代器
  num += 1
  if num == 5:
    line = ''.join([line.strip(),'羊小羚
'])  #里面就是对字符串进行操作了
  f2.write(line)
f1.close()
f2.close()

4. with语句

可以同时对多个文件同时操作,当with代码块执行完毕时,会自动关闭文件释放内存资源,不用特意加f.close() ,我们通过下面的示例体会with的用法和好处。用with语句重写8中的代码

num = 0
with open('file','r') as f1,open('file2','w',encoding='utf8') as f2:
  for line in f1:
    num += 1
    if num == 5:
      line = ''.join([line.strip(),'羊小羚'])
    f2.write(line)
原文地址:https://www.cnblogs.com/hq82/p/11336599.html