python进阶手册(1)

waterperl / 2023-06-20 / 原文

目录
  • 文件操作
    • 文件编码
    • 文件读写
    • 一次一密加解文件
  • 随机数
    • 随机数概述
    • 随机数编程
    • 循环生成随机数
  • 列表
    • 遍历列表
    • 切片的神奇操作
  • 文件操作
    • 一次一密加解密文件(续)
      • python对象的序列化
        • json
        • pickle
      • 保存和提取密码文件

文件操作

文件编码

通常情况下,文件是以 text mode 打开,就是说以字符串形式进行文件读写,这些字符串是以特定的 encoding 编码的。如果没有指定 encoding ,默认与平台有关的,,通常来说,指定UTF-8(现代事实标准),可这适应不同操作系统平台需要,使用 encoding="utf-8" 。
模式后面加上一个 'b' ,可以用 binary mode (二进制)打开文件,二进制模式的数据是以 bytes 对象的形式读写的。
在二进制模式下打开文件不能指定 encoding

with open("./test1.txt",encoding='utf-8') as f:
    txtStr = f.read()
    print(txtStr)

test1.txt内容,格式为utf-8

解决方案
\email\ham中的23.txt中第二段多了一个®(使用记事本打开显示的是“?”),导致解码失败,删除‘®’之后便可以继续执行。

正常输出

解决方案
\email\ham中的23.txt中第二段多了一个®(使用记事本打开显示的是“?”),导致解码失败,删除‘®’之后便可以继续执行。

上面代码关键在于

  • 使用 with 关键字处理文件对象,这样子句体结束后,文件会正确关闭,即便触发异常也可以关闭。

在调用 f.write() 时,如果未使用 with 关键字,或未调用 f.close(),会产生意想不到的后果,因为程序正常退出,也可能 致使要写入磁盘的内容没有写入,即:f.write() 的参数没有完全写入磁盘。

  • 使用open函数调用时,将 编码参数encoding,指定为utf-8,否则无法正常输出文件内容,会报以下错误:
File "g:\learn\py\learn1.py", line 2, in <module>
  txtStr = f.read()

builtins.UnicodeDecodeError: 'gbk' codec can't decode byte 0xa1 in position 10: illegal multibyte sequence

下面的盒子读取GBK格式的文件

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
f=open("news.txt","r",encoding="gbk")
data=f.read()
print(data)

下面代码读取gbk格式,写入utf8格式的新文件

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
f=open("news.txt","r",encoding="gbk")
data=f.read()
print(data)

f=open("newsutf8.txt","w",encoding="utf8")
f.write(data)

文件读写

  • 常用的文件读使用 f.read(size) 。
    f.read(size)它会读取文件内容,它会读取一些数据,并返回字符串(文本模式),或字节串对象(在二进制模式下)。 其中,size 是可选的数值参数。省略 size 或 size 为负数时,读取并返回整个文件的内容。size 取其他值时,读取并返回最多 size 个字符(文本模式)或 size 个字节(二进制模式)
    此外,f.readline() 从文件中读取单行数据,字符串末尾保留换行符(\n),只有在文件不以换行符结尾时,文件的最后一行才会省略换行符。

  • 文件写有f.write(string)。
    f.write(string) 把 string 的内容写入文件,并返回写入的字符数。

  • 还有以下常用函数

f.tell() 返回整数,给出文件对象在文件中的当前位置,表示为二进制模式下时从文件开始的字节数,以及文本模式下的意义不明的数字。

f.seek(offset, whence) 可以改变文件对象的位置。通过向参考点添加 offset 计算位置;参考点由 whence 参数指定。 whence 值为 0 时,表示从文件开头计算,1 表示使用当前文件位置,2 表示使用文件末尾作为参考点。省略 whence 时,其默认值为 0,即使用文件开头作为参考点。

下面代码读取广西文件并写入新的文本文件,但只读取前100个字符。

 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
f=open("news.txt","r",encoding="gbk")
data=f.read(100)
print(data)

f=open("newsutf8.txt","w",encoding="utf8")
f.write(data)

bytes 对象是由单个字节构成的不可变序列。 由于许多主要二进制协议都基于 ASCII 文本编码,因此 bytes 对象提供了一些仅在处理 ASCII 兼容数据时可用,并且在许多特性上与字符串对象紧密相关的方法。

class bytes([source[, encoding[, errors]]])

下面代码演示了读取一个GBK格式的文件前100个字符,然后以UTF8格式写入二进制模式文件中,因为使用的是UTF8格式,写入的仍然为文本文件。然后读取写入的新文件。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
f=open("news.txt","r",encoding="gbk")
data=f.read(100)
print(data)
print("------------")
f=open("newsutf8bytes.data","wb")
for fileChar in data:
    f.write(bytes(fileChar,encoding="utf8"))

f=open("newsutf8bytes.data","r",encoding="utf8")
data=f.read()
print(data)

bytes另外三种用法

指定长度的以零值填充的 bytes 对象: bytes(10)

通过由整数组成的可迭代对象: bytes(range(20))

通过缓冲区协议复制现有的二进制数据: bytes(obj)

一次一密加解文件

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

def getRandPassWd():
    passwd=random.randbytes(1)
    return passwd

import random
import os
random.seed(os.urandom(10))
passWords=[]

f=open("news.txt","r",encoding="gbk")
data=f.read()
f.close()
print(data)
print("-------加密-----")
with open("newsutf8bytes.data","wb") as f:
    for fileChar in data:
        passWords.append(getRandPassWd())
        fileWord=bytes(fileChar,encoding="utf8")
        encryptedData=int.from_bytes(fileWord, byteorder='big')^int.from_bytes(passWords[-1], byteorder='big')
        encryptedBytes=encryptedData.to_bytes(4,byteorder='big')
        encryptedStr="{:s}".format(str(encryptedBytes))
        print(encryptedStr,' ',fileChar,end=' |')
        f.write(encryptedBytes)
print("\n-------解密-----")
fileDecryptedData=[]
with open("newsutf8bytes.data","rb") as f,open("news.data","wb") as outFile:
    for i in range(len(passWords)):
        fileWord=f.read(4)
        decryptedData=int.from_bytes(fileWord, byteorder='big')^int.from_bytes(passWords[i], byteorder='big')
        decryptedStr=str(decryptedData.to_bytes(4,byteorder='big'),encoding='utf8')
        decryptedChar="{:s}".format(decryptedStr).lstrip("\x00")
        print(decryptedChar,end="")
        outFile.write(bytes(decryptedChar,encoding="utf8"))

运行结果

中国人的山河有两卷,一卷行于脚下,一卷纳于心怀。

  先人怀着敬畏与赤诚,在山河间且游且歌,将自然万象落墨于画卷诗行,并赋予它们风雅的别称——
CodeLite is an open source, free, cross platform IDE, specialized in C, C++, Rust, Python, PHP and JavaScript (mainly for backend developers using Node.js) programming languages which runs best on all major Platforms ( OSX, Windows and Linux )

You can Download CodeLite for the following OSs:

-------加密-----
b'\x00\xe4\xb8O'   中 |b'\x00\xe5\x9b\xec'   国 |b'\x00\xe4\xbae'   人 |b'\x00\xe7\x9a\xb7'   的 |b'\x00\xe5\xb1D'   山 |b'\x00\xe6\xb2g'   河 |b"\x00\xe6\x9c'"   有 |b'\x00\xe4\xb8\xb1'   两 |b'\x00\xe5\x8d\xef'   卷 |b'\x00\xef\xbc\x18'   , |b'\x00\xe4\xb8\xb8'   一 |b'\x00\xe5\x8d1'   卷 |b'\x00\xe8\xa1\xd3'   行 |b'\x00\xe4\xba\x16'   于 |b'\x00\xe8\x84\xc5'   脚 |b'\x00\xe4\xb8\x9f'   下 |b'\x00\xef\xbc('   , |b'\x00\xe4\xb8H'   一 |b'\x00\xe5\x8d4'   卷 |b'\x00\xe7\xba\xd1'   纳 |b'\x00\xe4\xba\xa5'   于 |b'\x00\xe5\xbf\xe0'   心 |b'\x00\xe6\x80\x86'   怀 |b'\x00\xe3\x80\xf4'   。 |b'\x00\x00\x00\x17'   
 |b'\x00\x00\x00\x1a'   
 |b'\x00\xe3\x80J'     |b'\x00\xe3\x80z'     |b'\x00\xe5\x85\xff'   先 |b'\x00\xe4\xbaq'   人 |b'\x00\xe6\x80<'   怀 |b'\x00\xe7\x9dV'   着 |b'\x00\xe6\x95\x98'   敬 |b'\x00\xe7\x95\xe0'   畏 |b'\x00\xe4\xb8\xb0'   与 |b'\x00\xe8\xb5s'   赤 |b'\x00\xe8\xaf\xc3'   诚 |b'\x00\xef\xbcU'   , |b'\x00\xe5\x9cq'   在 |b'\x00\xe5\xb1+'   山 |b"\x00\xe6\xb2'"   河 |b'\x00\xe9\x97\x95'   间 |b'\x00\xe4\xb89'   且 |b'\x00\xe6\xb8<'   游 |b'\x00\xe4\xb8\xe9'   且 |b'\x00\xe6\xad\x8a'   歌 |b'\x00\xef\xbc\xf1'   , |b'\x00\xe5\xb0G'   将 |b'\x00\xe8\x87m'   自 |b'\x00\xe7\x84+'   然 |b'\x00\xe4\xb8\xe2'   万 |b'\x00\xe8\xb1v'   象 |b'\x00\xe8\x90\x14'   落 |b'\x00\xe5\xa2\xb3'   墨 |b'\x00\xe4\xba\x84'   于 |b'\x00\xe7\x94\xb7'   画 |b'\x00\xe5\x8d\xbb'   卷 |b'\x00\xe8\xafO'   诗 |b'\x00\xe8\xa13'   行 |b'\x00\xef\xbc\xd6'   , |b'\x00\xe5\xb9\xb4'   并 |b'\x00\xe8\xb55'   赋 |b'\x00\xe4\xbav'   予 |b'\x00\xe5\xae\xae'   它 |b'\x00\xe4\xbbH'   们 |b'\x00\xe9\xa3\x18'   风 |b'\x00\xe9\x9b<'   雅 |b'\x00\xe7\x9a='   的 |b'\x00\xe5\x88%'   别 |b'\x00\xe7\xa7\xd4'   称 |b'\x00\xe2\x80\x8d'   — |b'\x00\xe2\x80\xa7'   — |b'\x00\x00\x00\x0b'   
 |b'\x00\x00\x009'   C |b'\x00\x00\x00\x17'   o |b'\x00\x00\x00h'   d |b'\x00\x00\x00\xbf'   e |b'\x00\x00\x00\xbb'   L |b'\x00\x00\x00\n'   i |b'\x00\x00\x00#'   t |b'\x00\x00\x00\x10'   e |b'\x00\x00\x00\xe3'     |b'\x00\x00\x00\x96'   i |b'\x00\x00\x00\x90'   s |b'\x00\x00\x006'     |b'\x00\x00\x00\x15'   a |b'\x00\x00\x00"'   n |b'\x00\x00\x00?'     |b'\x00\x00\x00A'   o |b'\x00\x00\x00\xe9'   p |b'\x00\x00\x00\xd2'   e |b'\x00\x00\x00\xb4'   n |b'\x00\x00\x00O'     |b'\x00\x00\x00l'   s |b'\x00\x00\x00\xf8'   o |b'\x00\x00\x009'   u |b'\x00\x00\x00R'   r |b'\x00\x00\x00\x1d'   c |b'\x00\x00\x00\x00'   e |b'\x00\x00\x00\xd5'   , |b'\x00\x00\x00\xfb'     |b'\x00\x00\x00J'   f |b'\x00\x00\x00\\'   r |b'\x00\x00\x00\xa5'   e |b'\x00\x00\x00 '   e |b'\x00\x00\x00z'   , |b'\x00\x00\x00s'     |b'\x00\x00\x00\x0b'   c |b'\x00\x00\x00\xa5'   r |b'\x00\x00\x00\xdb'   o |b'\x00\x00\x00\x96'   s |b'\x00\x00\x00K'   s |b'\x00\x00\x00|'     |b'\x00\x00\x00\n'   p |b'\x00\x00\x00\xf7'   l |b'\x00\x00\x00T'   a |b'\x00\x00\x00\x87'   t |b'\x00\x00\x00\xff'   f |b'\x00\x00\x00\xfa'   o |b'\x00\x00\x00O'   r |b'\x00\x00\x00~'   m |b'\x00\x00\x00\xa0'     |b'\x00\x00\x00\x8a'   I |b'\x00\x00\x00|'   D |b'\x00\x00\x00&'   E |b'\x00\x00\x00\xc7'   , |b'\x00\x00\x00\xfa'     |b'\x00\x00\x00\xb4'   s |b'\x00\x00\x00\xc4'   p |b'\x00\x00\x00S'   e |b'\x00\x00\x00\xde'   c |b'\x00\x00\x00\xa8'   i |b'\x00\x00\x00\x1d'   a |b'\x00\x00\x00!'   l |b'\x00\x00\x00\x9a'   i |b'\x00\x00\x00\t'   z |b'\x00\x00\x00\xb2'   e |b'\x00\x00\x00\x92'   d |b'\x00\x00\x00\xb8'     |b'\x00\x00\x00g'   i |b'\x00\x00\x00\xc9'   n |b'\x00\x00\x00\xb0'     |b'\x00\x00\x00\xe5'   C |b'\x00\x00\x00\xfa'   , |b'\x00\x00\x00\xf8'     |b'\x00\x00\x00\xeb'   C |b'\x00\x00\x00\x19'   + |b'\x00\x00\x00\xb4'   + |b'\x00\x00\x00\x05'   , |b'\x00\x00\x00\xdb'     |b'\x00\x00\x00I'   R |b'\x00\x00\x00\xff'   u |b'\x00\x00\x00`'   s |b'\x00\x00\x00\x83'   t |b'\x00\x00\x00\xec'   , |b'\x00\x00\x00l'     |b'\x00\x00\x00\xd3'   P |b'\x00\x00\x00V'   y |b'\x00\x00\x00\xd5'   t |b'\x00\x00\x00\xd4'   h |b"\x00\x00\x00'"   o |b'\x00\x00\x00\xe3'   n |b'\x00\x00\x00X'   , |b'\x00\x00\x00\x91'     |b'\x00\x00\x00\xfa'   P |b'\x00\x00\x00A'   H |b'\x00\x00\x00N'   P |b'\x00\x00\x00\xe6'     |b'\x00\x00\x00\x01'   a |b'\x00\x00\x00\x96'   n |b'\x00\x00\x00&'   d |b'\x00\x00\x00>'     |b'\x00\x00\x00\x03'   J |b'\x00\x00\x00z'   a |b'\x00\x00\x00\xf3'   v |b'\x00\x00\x00@'   a |b'\x00\x00\x00\x05'   S |b'\x00\x00\x00,'   c |b'\x00\x00\x00\xc5'   r |b'\x00\x00\x00\xf0'   i |b'\x00\x00\x00w'   p |b'\x00\x00\x00P'   t |b'\x00\x00\x00\xa5'     |b'\x00\x00\x001'   ( |b'\x00\x00\x00\xe8'   m |b'\x00\x00\x00\xca'   a |b'\x00\x00\x00\xb5'   i |b'\x00\x00\x00\x04'   n |b'\x00\x00\x00>'   l |b'\x00\x00\x00\x8d'   y |b'\x00\x00\x00\xd6'     |b'\x00\x00\x00\xd4'   f |b'\x00\x00\x00I'   o |b'\x00\x00\x00\xb2'   r |b'\x00\x00\x00!'     |b'\x00\x00\x00\xea'   b |b'\x00\x00\x00\xb1'   a |b'\x00\x00\x00X'   c |b'\x00\x00\x00\xf9'   k |b'\x00\x00\x00V'   e |b'\x00\x00\x004'   n |b'\x00\x00\x00\x16'   d |b'\x00\x00\x00\xb9'     |b'\x00\x00\x00\x1a'   d |b'\x00\x00\x00\xea'   e |b'\x00\x00\x00\xbb'   v |b'\x00\x00\x00\x8c'   e |b'\x00\x00\x00w'   l |b'\x00\x00\x00\x95'   o |b'\x00\x00\x00J'   p |b'\x00\x00\x00\x0c'   e |b'\x00\x00\x00\x08'   r |b'\x00\x00\x00\xae'   s |b'\x00\x00\x00\xe5'     |b'\x00\x00\x00\x02'   u |b'\x00\x00\x00\x85'   s |b'\x00\x00\x00('   i |b'\x00\x00\x00\xc1'   n |b'\x00\x00\x009'   g |b'\x00\x00\x00\x8f'     |b'\x00\x00\x00T'   N |b'\x00\x00\x00I'   o |b'\x00\x00\x00\t'   d |b'\x00\x00\x00\xa6'   e |b'\x00\x00\x00\x9a'   . |b'\x00\x00\x00F'   j |b'\x00\x00\x00\xad'   s |b'\x00\x00\x00L'   ) |b'\x00\x00\x00\x9a'     |b'\x00\x00\x00\xff'   p |b'\x00\x00\x00\xfb'   r |b'\x00\x00\x00`'   o |b'\x00\x00\x00A'   g |b'\x00\x00\x00p'   r |b'\x00\x00\x00\x98'   a |b'\x00\x00\x00\xc4'   m |b'\x00\x00\x00\xc6'   m |b'\x00\x00\x00\x91'   i |b'\x00\x00\x00T'   n |b'\x00\x00\x00}'   g |b'\x00\x00\x00\x9c'     |b'\x00\x00\x00\x8c'   l |b'\x00\x00\x00\xb0'   a |b'\x00\x00\x00+'   n |b'\x00\x00\x00\xac'   g |b'\x00\x00\x00\xea'   u |b'\x00\x00\x00\x02'   a |b'\x00\x00\x00\xcd'   g |b'\x00\x00\x004'   e |b'\x00\x00\x00\xf4'   s |b'\x00\x00\x00g'     |b'\x00\x00\x00\xe4'   w |b'\x00\x00\x00P'   h |b'\x00\x00\x00R'   i |b'\x00\x00\x00\x9d'   c |b'\x00\x00\x00\xbd'   h |b"\x00\x00\x00'"     |b'\x00\x00\x00\x94'   r |b'\x00\x00\x00\x19'   u |b'\x00\x00\x00c'   n |b'\x00\x00\x00s'   s |b'\x00\x00\x00\x1e'     |b'\x00\x00\x00\x84'   b |b'\x00\x00\x00h'   e |b'\x00\x00\x00Y'   s |b'\x00\x00\x00\x8f'   t |b'\x00\x00\x002'     |b'\x00\x00\x00\xfe'   o |b'\x00\x00\x00\xba'   n |b'\x00\x00\x00\xdb'     |b'\x00\x00\x00\xe6'   a |b'\x00\x00\x00\xe5'   l |b'\x00\x00\x00p'   l |b'\x00\x00\x00\xcb'     |b'\x00\x00\x00\xd5'   m |b'\x00\x00\x00^'   a |b'\x00\x00\x001'   j |b'\x00\x00\x00}'   o |b'\x00\x00\x00\xea'   r |b'\x00\x00\x00\x99'     |b'\x00\x00\x00U'   P |b'\x00\x00\x00\x87'   l |b'\x00\x00\x00\xa5'   a |b'\x00\x00\x00\xa5'   t |b'\x00\x00\x00\xd6'   f |b'\x00\x00\x00\xc6'   o |b'\x00\x00\x00\x19'   r |b'\x00\x00\x00%'   m |b'\x00\x00\x00!'   s |b'\x00\x00\x00\xc0'     |b'\x00\x00\x00\xc4'   ( |b'\x00\x00\x00\xee'     |b'\x00\x00\x00\x94'   O |b'\x00\x00\x00w'   S |b'\x00\x00\x00\xc0'   X |b'\x00\x00\x00\x8b'   , |b'\x00\x00\x00\xb7'     |b'\x00\x00\x00\x9c'   W |b'\x00\x00\x00:'   i |b'\x00\x00\x00\xb9'   n |b'\x00\x00\x00\xf4'   d |b'\x00\x00\x00\xa1'   o |b'\x00\x00\x00\xa2'   w |b'\x00\x00\x000'   s |b'\x00\x00\x00y'     |b'\x00\x00\x00\xf5'   a |b'\x00\x00\x00*'   n |b'\x00\x00\x00\xd5'   d |b'\x00\x00\x009'     |b'\x00\x00\x00\xf7'   L |b'\x00\x00\x00\x94'   i |b'\x00\x00\x00\xad'   n |b'\x00\x00\x00\xe1'   u |b'\x00\x00\x00P'   x |b'\x00\x00\x00;'     |b'\x00\x00\x00\x1c'   ) |b'\x00\x00\x00"'   
 |b'\x00\x00\x00\xf9'   
 |b'\x00\x00\x00\x85'   Y |b'\x00\x00\x00\x19'   o |b'\x00\x00\x00\xe4'   u |b'\x00\x00\x00R'     |b'\x00\x00\x00\xd9'   c |b'\x00\x00\x00\xe4'   a |b'\x00\x00\x00G'   n |b'\x00\x00\x00A'     |b'\x00\x00\x00\xaa'   D |b'\x00\x00\x004'   o |b'\x00\x00\x00\x1a'   w |b'\x00\x00\x00\\'   n |b'\x00\x00\x00\x0f'   l |b'\x00\x00\x00x'   o |b'\x00\x00\x00\x19'   a |b'\x00\x00\x00('   d |b'\x00\x00\x00\xe2'     |b'\x00\x00\x00P'   C |b'\x00\x00\x00\xc7'   o |b'\x00\x00\x00\x15'   d |b'\x00\x00\x00O'   e |b'\x00\x00\x00\x92'   L |b'\x00\x00\x00F'   i |b'\x00\x00\x00:'   t |b'\x00\x00\x00B'   e |b'\x00\x00\x00\xb3'     |b'\x00\x00\x00\xd9'   f |b'\x00\x00\x00|'   o |b'\x00\x00\x00\x88'   r |b'\x00\x00\x00\x83'     |b'\x00\x00\x00\xe4'   t |b'\x00\x00\x00F'   h |b'\x00\x00\x00\xd1'   e |b'\x00\x00\x00\xb3'     |b'\x00\x00\x00;'   f |b'\x00\x00\x00<'   o |b'\x00\x00\x00P'   l |b'\x00\x00\x00\xb9'   l |b'\x00\x00\x00P'   o |b'\x00\x00\x00m'   w |b'\x00\x00\x00f'   i |b'\x00\x00\x00X'   n |b'\x00\x00\x00\x84'   g |b'\x00\x00\x00\xa7'     |b'\x00\x00\x00\xfe'   O |b'\x00\x00\x00N'   S |b'\x00\x00\x00\x84'   s |b'\x00\x00\x00C'   : |b'\x00\x00\x00D'   
 |
-------解密-----
中国人的山河有两卷,一卷行于脚下,一卷纳于心怀。

  先人怀着敬畏与赤诚,在山河间且游且歌,将自然万象落墨于画卷诗行,并赋予它们风雅的别称——
CodeLite is an open source, free, cross platform IDE, specialized in C, C++, Rust, Python, PHP and JavaScript (mainly for backend developers using Node.js) programming languages which runs best on all major Platforms ( OSX, Windows and Linux )

You can Download CodeLite for the following OSs:

随机数

随机数概述

随机数是专门的随机试验的结果,随机数最重要的特性是:它所产生的后面的那个数与前面的那个数毫无关系。
产生随机数有多种不同的方法,这些方法被称为随机数发生器,随机数可分为真随机数和伪随机数,它们的生成方法如下:
1、真随机数可采用这些方法:获取cpu频率与温度的不确定性以及统计一段时间的运算次数每次都会产生不同的值,系统时间的误差以及声卡的底噪等。
2、在实际应用中往往使用伪随机数就足够了。伪随机数的数列是“似乎”随机的数,实际上它们是通过一个固定的、可以重复的计算方法产生的。计算机产生的随机数有很长的周期性,它们不真正地随机,因为它们实际上是可以计算出来的,但是它们具有类似于随机数的统计特征。这样的发生器叫做伪随机数发生器。

随机数编程

Python使用 Mersenne Twister 作为核心生成器,它产生 53 位精度浮点数,周期为 2的19937次方-1。
Mersenne Twister算法中文翻译为马特赛特旋转演算法,是Makoto Matsumoto (松本)和Takuji Nishimura (西村)于1997年开发的,基于有限二进制字段上的矩阵线性再生,可以快速产生高质量的伪随机数。
Python3通常使用random 模块生成伪随机数,该模块实现了各种分布的伪随机数生成器。
1、random
random() 是基本函数,它在半开放区间 [0.0,1.0) 内均匀生成随机浮点数,函数的功能是:返回 [0.0, 1.0) 范围内的下一个随机浮点数,调用方法如下:
random.random()
下面程序产生3个随机数。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#2-3-2-1.py
import random
rndNum=random.random()
print(rndNum)
rndNum=random.random()
print(rndNum)
rndNum=random.random()
print(rndNum)
rndNum=random
print(rndNum)

程序运行结果如下:
0.7570246127141028
0.5169027763180408
0.9060437508485364
uniform
函数功能是:返回一个随机浮点数 N ,当 a <= b 时 a <= N <= b ,当 b < a 时 b <= N <= a 。调用方法如下:
random.uniform(a, b)
下面程序产生3个0-10之间的随机数。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#2-3-2-2.py
import random
rndNum=random.uniform(0,10)
print(rndNum)
rndNum=random.uniform(0,10)
print(rndNum)
rndNum=random.uniform(0,10)
print(rndNum)
rndNum=random
print(rndNum)

normalvariate
函数功能是:返回正态分布的随机数。调用方法如下:
random.normalvariate(mu, sigma)
其中,mu 是平均值,sigma 是标准差。
下面程序产生3个平均值为mu,标准差为sigma的随机数。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#2-3-2-3.py
import random
rndNum=random.normalvariate(2.0,5.6)
print(rndNum)
rndNum=random.normalvariate(2.0,5.6)
print(rndNum)
rndNum=random.normalvariate(2.0,5.6)
print(rndNum)
程序执行结果如下:
-5.106617491883201
-9.542448274385015
2.7602239773528128

random.randbytes
生成n个随机字节数据。调用格式如下:
random.randbytes(n)
程序如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#2-3-2-4.py
import random
xbytes=random.randbytes(10)
for i in xbytes:
    print("%x"%i,end=”,”)
print("----")
xbytes=random.randbytes(2)
for i in xbytes:
    print("%x"%i,end=”,”)

运行程序后,将生成2组字节随机数,第1组由10个字节组成,第2组由2个字节组成。运行结果如下:
93,ee,6d,50,11,6d,8b,e8,6f,b4,
38,f7,
random.sample
返回从总体序列或集合中选择的唯一元素的 k 长度列表,用于无重复的随机抽样,比如:要改变一个不可变的序列并返回一个新的打乱列表,调用格式如下:
random.sample(population, k, *, counts=None)
程序如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#2-3-2-4.py
import random
x=list(range(10))
print(x)
y=random.sample(x,len(x))
print(y)

上述程序首先输出原列表x内容,数字按从0到9依次排列,然后打乱顺序后生成y,并输出。
提示:类似的random.shuffle函数在Python 3.9版废弃, 将在3.11版本中删除。
randint
返回随机整数 N 满足 a <= N <= b。调用格式如下:
random.randint(a, b)
程序如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#2-3-2-6.py
import random
x=random.randint(5,10)
print(x)
y=random.randint(2,8)
print(y)

程序运行后,生成2个随机数,第1个随机数在5到10之间,第2个随机数在2到8之间,运行结果如下:
8
6
choice
从非空序列 seq 返回一个随机元素。调用格式如下:
random.choice(seq)
程序如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#2-3-2-7.py
import random
x=list(range(5,20))
y=random.choice(x)
print(y)
y=random.choice(x)
print(y)

程序运行生成2个随机数,运行结果如下:
8
18
8、Seed
初始化随机数生成器,指定随机种子,随机种子(Random Seed)的作用是:以真随机数(随机种子)为初始条件的生成随机数。因为对于一个伪随机数生成器,从相同的随机数种子出发,会得到相同的随机数序列,当序列用完后,随机数就重复出现,所以,应在取得随机数若干次后更换种子。调用格式如下。
random.seed(a=None, version=2)
1、如果 a 被省略或为 None ,则使用当前系统时间。
2、如果操作系统提供随机源,则通过os.urandom()取得随机源,该函数返回大小为 size 的字符串,它是适合加密使用的随机字节。调用格式如下:
os.urandom(size)
程序如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#2-3-2-8.py
import random
import os
x=random.randint(5,10)
print(x)
print(os.urandom(10))
random.seed(os.urandom(10))
x=random.randint(5,10)
print(x)
random.seed()
x=random.randint(5,10)
print(x)

程序运行结果如下:

6
b'\xd1w"\xeb|EI\x97%\xb0'
7
8

循环生成随机数

一、for循环
Python中的for语句用于循环,但与C++等语言略有不同,不能设置循环初始化变量、每次循环要执行的语句以及循环终止条件,而是按顺序遍历序列的项(列表或一个字符串)。

程序2-3-3-1.py演示for循环的使用方法。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#2-3-3-1.py
for i in [0,1,2,3,4,5]:
    print(i,end=",")
print()
for c in "abcdefg":
    print(c,end=",")
print()
for x in ['aa','bb','cc']:
    print(x,end=",")
print()

程序执行结果如下:
0,1,2,3,4,5,
a,b,c,d,e,f,g,
aa,bb,cc,
程序2-3-3-1.py首先在列表[0,1,2,3,4,5]中迭代循环,依次访问该列表的每个项;然后在字符串"abcdefg"中迭代循环,依次访问字符串中的每个字符;最后在列表['aa','bb','cc']中迭代循环,依次访问该列表中的每个字符串。
提示:print(x,end=",")这类语句中的end参数表示,打印出指定内容后的结尾符号,默认情况下是换行,因此不指定end参数的情况下,print函数输出内容后会换行,但程序2-3-3-1.py的print函数指定了结尾符号为“,”,因此,每输出迭代内容的一项后,输出“,”。
二、range
range与for循环搭配使用的情况较多,它的使用格式如下:
range(start, stop[, step])
其中,start表示起始值,stop表示终止值(不包括终止值本身),step表示每次迭代的步长。如果省略了step参数,则默认为1;省略了start参数,则默认为0,2者可都省略,调用格式如下:
range(stop)
range不是一个列表,需要通过迭代的方法来访问它。比如,下面代码试图直接输出range中的每个项,是不行的。

>>>range(10)
range(0, 10)

正确的方法是通过迭代来使用,如下面代码所示:

>>>for i in range(10):
...   print(i)
...
0
1
2
3
4
5
6
7
8
9

观察上述代码执行结果,可以发现,range(10)实质不包括10,只包括0-9的整数,10是stop参数,该参数指定的终止值是指小于该终止值,而不是小于或等于该终止值,即0<=range(10)的每个项<10。
当然,也可以把range转换为list来输出,如下面代码所示:

>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(1, 11))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> list(range(0, 30, 5))
[0, 5, 10, 15, 20, 25]

上述代码中最后2行指定了步长为5,因此,每隔5输出一个整数,因为不能包含30,所以只输出到25就截止。
步长为正,则range的第i项值为:r[i] = start + stepi 。而步长为负,range的第i项值仍然是:r[i] = start + stepi ,但i >= 0且r[i] > stop。比如:

>>> list(range(0, -10, -1))
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]

三、循环产生随机数
1、程序2-3-3-2.py生成5个0-1之间的随机数。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#2-3-3-2.py
import random
for i in range(5):
    print(random.random(),end=",")
程序运行结果如下:
0.6072850285700557,0.6503186134829979,0.14500377381022078,0.4423421851318021,0.8041403662570388,

2、程序2-3-3-3.py生成10个4位随机二进制位的随机数。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#2-3-3-3.py
import random
for i in range(5):
    print(random.getrandbits(4))

运行程序2-3-3-3.py,结果如下:
14
9
14
11
8
random.getrandbits函数的调用格式如下:
random.getrandbits(N)
其功能是:生成N位随机位(二进制)的非负 Python 整数,在可能的情况下,getrandbits() 可比randint()能容纳更大的区间范围 ,即:可处理任意大的区间。
比如:N为1,则处理1位二进制位,即:0-1的区间。如下面代码所示:

>>>random.getrandbits(1)
0
>>>random.getrandbits(1)
1
>>>random.getrandbits(1)
0

N为3,则处理3位二进制位,最大可处理20+21+2^2=1+2+4=7的整数,即:0-6的空间。

>>>random.getrandbits(3)
6

N可以更大,比如N可以为280,如下面代码所示:

>>>random.getrandbits(280)
1754469414458690307206641240574745122735215429162475470025306094824265467380673171492

列表

遍历列表

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
x=[1,2,3,4,5,6,7,8]
for i in x:
    print(i)

通过for in循环可以方便遍历列表,但记住,这种方式是只读的

for i in x:
    i=i*10
print(x)

上面这种操作是无意义的,徒劳的。
通过索引方式遍历列表,要注意了,这是可以修改列表元素的,要慎重

for j  in range(len(x)):
    x[j]=x[j]*10

测试上面例子

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
x=[1,2,3,4,5,6,7,8]
for i in x:
    print(i)
for i in x:
    i=i*10
print(x)
for j  in range(len(x)):
    x[j]=x[j]*10
print(x)
1
2
3
4
5
6
7
8
[1, 2, 3, 4, 5, 6, 7, 8]
[10, 20, 30, 40, 50, 60, 70, 80]

切片的神奇操作

slice 对象代表由 range(start, stop, step) 指定索引集的切片。 其中参数 start 和 step 的默认值为
None。切片对象具有只读数据属性 start 、stop 和
step,只是返回对应的参数值(或默认值)。这几个属性没有其他明确的功能;不过 NumPy
和其他第三方扩展会用到。在使用扩展索引语法时,也会生成切片对象。例如: a[start:stop:step] 或 a[start:stop,
i]。 另一种方案是返回迭代器对象,itertools.islice() 。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
x=[1,2,3,4,5,6,7,8]
for i in x:
    print(i)
x[1:2]=[11,22]
print(x)
x[:]=[12,13]
print(x)  

注意了,通过切片修改列表元素,可以一次修改大于切片数量的元素

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
x=[1,2,3,4,5,6,7,8]
for i in x:
    print(i)
  
x[1:2]=[101,103,104,105,106]
print(x)

但是这并不意味着使用切片就是直接对列表进行操作,如果将切片赋值给一个变量,那么该变量就是切片切取的部分列表元素的复制体,而不是列表元素本身。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
x=[1,2,3,4,5,6,7,8]
for i in x:
    print(i)
y1=x[:]
print(y1)
y2=x[2:4]
print(y2)
y1.append(11)
y2.append(22)
print(y1)
print(y2)
print(x)
1
2
3
4
5
6
7
8
[1, 2, 3, 4, 5, 6, 7, 8]
[3, 4]
[1, 2, 3, 4, 5, 6, 7, 8, 11]
[3, 4, 22]
[1, 2, 3, 4, 5, 6, 7, 8]

文件操作

一次一密加解密文件(续)

上节,完成了对GBK文本文本的加密,加密后,生成新的文件,并进行解密,然后,重新生成文件。
这节,需要解决的是密码文件的保存,因为是一次一密,即一个字符一个密码,密码采用的是随机生成方式,这意味着双方都需要持有密码文件,里面依次保存了所有密码。

python对象的序列化

json

JSON 格式通常用于现代应用程序的数据交换,可以轻松保存和提取python对象的 JSON 字符串。但是,它是将 obj 序列化为 JSON 格式的字符串,不能序列化其它类型的对象。

JSON 中的键-值对中的键永远是 str 类型的。当一个对象被转化为 JSON
时,字典中所有的键都会被强制转换为字符串。这所造成的结果是字典被转换为 JSON 然后转换回字典时可能和原来的不相等。
换句话说,如果 x 具有非字符串的键,则有 loads(dumps(x)) != x。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
x=[[1,2],[10,20]]
result=json.dumps(x)
print(result)

运行结果:
[[1, 2], [10, 20]]

  • 使用json对密码文件保存
    使用json.dumps 将 obj 序列化为 JSON 格式的 str
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json

with open("password.txt","w",encoding="utf8") as f:
    passwds=[111,23543215,3734,124,12439]
    result=json.dumps(passwds)
    f.write(result)


  • 使用json对密码文件取
    json.load 将JSON 反序列化为一个 Python 对象。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json

with open("password.txt","r",encoding="utf8") as f:
    data=f.read()
    passwds=json.loads(data)
    print(passwds)

输出

[111, 23543215, 3734, 124, 12439]
  • dump和load
    dump() 将 obj 序列化为 JSON 格式化流形式。第1个参数是对象,第2个参数是文件对象。
    load()也一样,用来解码对象, 将文件对象 (一个支持 .read() 并包含一个 JSON 文档的 text file 或者 binary file) 反序列化为一个 Python 对象。第1个参数是已打开、供读取的 binary file 或 text file文件对象,返回对象。

JSON文件必须以UTF-8编码。当打开JSON文件作为一个 text file 用于读写时,使用 encoding="utf-8" 。

读密码文件

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json

with open("password.txt","r",encoding="utf8") as f:
    passwds=json.load(f)
    print(passwds)


写密码文件

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
passwds=[111,23253,423634,12,412,99]
with open("password.txt","w",encoding="utf8") as f:
    json.dump(passwds,f)


应用到前面的一次一密例子中,是不适合的,因为它的密码是元素类型为bytes型的列表。
使用json是无法完成这个任务的,它不支持bytes型。

>>>x=[11,22]
>>>json.dumps(x)
'[11, 22]'
>>>x=['11','22']
>>>json.dumps(x)
'["11", "22"]'
>>>x=[b'01',b'a2']
json.dumps(x)
Traceback (most recent call last):
........
builtins.TypeError: Object of type bytes is not JSON serializable

pickle

必须使用pickle
模块 pickle 实现了对一个 Python 对象结构的二进制序列化和反序列化。 "pickling" 是将 Python 对象及其所拥有的层次结构转化为一个字节流的过程,而 "unpickling" 是相反的操作,会将(来自一个 binary file 或者 bytes-like object 的)字节流转化回一个对象层次结构。

保存和提取密码文件

def savePassTofile(passWd,fileName):
    import pickle
    with open(fileName,"wb") as f:
        pickle.dump(passWd,f)

def readPassFromFile(fileName):
    import pickle
    with open(fileName,"rb") as f:
        passwds=pickle.load(f)
        return passwds  

完整代码如下

#!/usr/bin/env python3
# -*- coding: utf-8 -*-



import random
import os

def getRandPassWd():
    passwd=random.randbytes(1)
    return passwd

def savePassTofile(passWd,fileName):
    import pickle
    with open(fileName,"wb") as f:
        pickle.dump(passWd,f)

def readPassFromFile(fileName):
    import pickle
    with open(fileName,"rb") as f:
        passwds=pickle.load(f)
        return passwds  
    




if __name__=="__main__":
    random.seed(os.urandom(10))
    passWords=[]    
    f=open("news.txt","r",encoding="utf8")
    data=f.read()
    f.close()
    print(data)
    print("-------加密-----")
    with open("newsutf8bytes.data","wb") as f:
        for fileChar in data:
            passWords.append(getRandPassWd())
            fileWord=bytes(fileChar,encoding="utf8")
            encryptedData=int.from_bytes(fileWord, byteorder='big')^int.from_bytes(passWords[-1], byteorder='big')
            encryptedBytes=encryptedData.to_bytes(4,byteorder='big')
            encryptedStr="{:s}".format(str(encryptedBytes))
            print(encryptedStr,' ',fileChar,end=' |')
            f.write(encryptedBytes)
    savePassTofile(passWords,"passwd.data")
    print("\n-------解密-----")
    fileDecryptedData=[]
    passWords=readPassFromFile("passwd.data")
    with open("newsutf8bytes.data","rb") as f,open("news.data","wb") as outFile:
        for i in range(len(passWords)):
            fileWord=f.read(4)
            decryptedData=int.from_bytes(fileWord, byteorder='big')^int.from_bytes(passWords[i], byteorder='big')
            decryptedStr=str(decryptedData.to_bytes(4,byteorder='big'),encoding='utf8')
            decryptedChar="{:s}".format(decryptedStr).lstrip("\x00")
            print(decryptedChar,end="")
            outFile.write(bytes(decryptedChar,encoding="utf8"))

运行结果如下

Geany是一个小巧的使用GTK+2开发的跨平台的开源集成开发环境,以GPL许可证分发源代码,是免费的自由软件。
当前版本:1.36。
该软件小巧、启动迅速,缺点是界面简陋、功能简单。

-------加密-----
b'\x00\x00\x00\xc9'   G |b'\x00\x00\x00\x9f'   e |b'\x00\x00\x00\x0b'   a |b'\x00\x00\x00\x1a'   n |b'\x00\x00\x00\x07'   y |b'\x00\xe6\x98\xc2'   是 |b'\x00\xe4\xb8-'   一 |b'\x00\xe4\xb8\xa3'   个 |b'\x00\xe5\xb0\x9d'   小 |b'\x00\xe5\xb7\xe6'   巧 |b'\x00\xe7\x9a\x80'   的 |b'\x00\xe4\xbd\x14'   使 |b'\x00\xe7\x94\xbc'   用 |b'\x00\x00\x00P'   G |b'\x00\x00\x00\xd4'   T |b'\x00\x00\x00\xaf'   K |b'\x00\x00\x00k'   + |b'\x00\x00\x00\xe4'   2 |b'\x00\xe5\xbc\xe7'   开 |b'\x00\xe5\x8f\xd9'   发 |b'\x00\xe7\x9ax'   的 |b'\x00\xe8\xb7!'   跨 |b'\x00\xe5\xb9J'   平 |b'\x00\xe5\x8fl'   台 |b'\x00\xe7\x9a\xf2'   的 |b'\x00\xe5\xbcR'   开 |b'\x00\xe6\xba\xce'   源 |b'\x00\xe9\x9b\xf7'   集 |b'\x00\xe6\x88\xd7'   成 |b"\x00\xe5\xbc'"   开 |b'\x00\xe5\x8fU'   发 |b'\x00\xe7\x8e\xf4'   环 |b'\x00\xe5\xa2\xcc'   境 |b'\x00\xef\xbc7'   , |b'\x00\xe4\xbb\xb2'   以 |b'\x00\x00\x00t'   G |b'\x00\x00\x00`'   P |b'\x00\x00\x000'   L |b'\x00\xe8\xae\x95'   许 |b'\x00\xe5\x8f\x84'   可 |b'\x00\xe8\xaf\x1b'   证 |b'\x00\xe5\x88\xdf'   分 |b'\x00\xe5\x8f\x81'   发 |b'\x00\xe6\xbaC'   源 |b'\x00\xe4\xbb\\'   代 |b'\x00\xe7\xa0\x15'   码 |b'\x00\xef\xbcv'   , |b'\x00\xe6\x98\xa7'   是 |b'\x00\xe5\x85\x08'   免 |b'\x00\xe8\xb4f'   费 |b'\x00\xe7\x9a\xd4'   的 |b'\x00\xe8\x87\x1f'   自 |b'\x00\xe7\x94\x94'   由 |b'\x00\xe8\xbd*'   软 |b'\x00\xe4\xbb\x02'   件 |b'\x00\xe3\x80\x9d'   。 |b'\x00\x00\x007'   
 |b'\x00\xe5\xbdB'   当 |b'\x00\xe5\x89\xff'   前 |b'\x00\xe7\x89\xe7'   版 |b'\x00\xe6\x9c\xfe'   本 |b'\x00\xef\xbc['   : |b'\x00\x00\x00\xd4'   1 |b'\x00\x00\x00m'   . |b'\x00\x00\x00O'   3 |b'\x00\x00\x00v'   6 |b'\x00\xe3\x80\xea'   。 |b'\x00\x00\x00\x9d'   
 |b'\x00\xe8\xaf\xf8'   该 |b'\x00\xe8\xbd$'   软 |b'\x00\xe4\xbb\xf4'   件 |b'\x00\xe5\xb0\xee'   小 |b'\x00\xe5\xb7\xaf'   巧 |b'\x00\xe3\x80\x93'   、 |b'\x00\xe5\x90\x11'   启 |b'\x00\xe5\x8a\xdc'   动 |b'\x00\xe8\xbf\x9b'   迅 |b'\x00\xe9\x80\t'   速 |b'\x00\xef\xbc\x9c'   , |b'\x00\xe7\xbc\x19'   缺 |b'\x00\xe7\x82U'   点 |b'\x00\xe6\x98E'   是 |b'\x00\xe7\x95\xdf'   界 |b'\x00\xe9\x9d\xa7'   面 |b'\x00\xe7\xaek'   简 |b'\x00\xe9\x99\xd9'   陋 |b'\x00\xe3\x80\x0c'   、 |b'\x00\xe5\x8aO'   功 |b'\x00\xe8\x83\xbd'   能 |b'\x00\xe7\xae\x05'   简 |b'\x00\xe5\x8di'   单 |b'\x00\xe3\x80\xe7'   。 |b'\x00\x00\x00\r'   
 |
-------解密-----
Geany是一个小巧的使用GTK+2开发的跨平台的开源集成开发环境,以GPL许可证分发源代码,是免费的自由软件。
当前版本:1.36。
该软件小巧、启动迅速,缺点是界面简陋、功能简单。

和json 模块的区别

  • JSON 是一个文本序列化格式(它输出 unicode 文本,尽管在大多数时候它会接着以 utf-8 编码),而 pickle 是一个二进制序列化格式;

  • JSON 是我们可以直观阅读的,而 pickle 不是;

  • JSON是可互操作的,在Python系统之外广泛使用,而pickle则是Python专用的;

  • 默认情况下,JSON 只能表示 Python 内置类型的子集,不能表示自定义的类;但 pickle 可以表示大量的 Python 数据类型(可以合理使用 Python 的对象内省功能自动地表示大多数类型,复杂情况可以通过实现 specific object APIs 来解决)。

  • 不像pickle,对一个不信任的JSON进行反序列化的操作本身不会造成任意代码执行漏洞。