【Python基础 day21】random & 序列化 & 异常处理 & Os

random模块:选择功能只能对序列类型进行迭代

>>> import random
#随机生成小数
>>> random.random()#random.random(),只能生成0-1之间的小数
0.13410910544892163
>>> random.random(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: random() takes no arguments (1 given)
>>> random.uniform(1,2)#按照指定的区间进行生成小数
1.7771163573646869
>>> random.randrange(1,3)#random.randrange(),随机取指定区间的值,顾头不顾尾,可以加步长
2

#随机生成整数
>>> random.randrange(1,3)
1
>>> random.randrange(1,10,2)
7
>>> random.randint(1,2)#与random.randrange()的区别可以取大于等于1,小于等于2的数
2
>>> random.randint(1,2)
1

#随机选择一个数,参数不能为字典,
>>> random.choice([1,'23',[4,5]])#随机选择一个数
'23'

>>> random.sample([1,'23',[4,5]],3)#随机返回sample函数中第二个参数,
指定的个数,必须指定随机选择的个数,返回的list
[[4, 5], '23', 1] #打乱列表顺序,shuffle 该函数没有返回值, >>> item = [1,2,3,4,5] >>> random.shuffle(item) >>> a = random.shuffle(item) >>> print(a,type(a)) None <class 'NoneType'> >>> random.shuffle(item) >>> item [5, 2, 1, 3, 4] >>> random.shuffle(item) >>> item [4, 1, 3, 5, 2]

实现验证码:

import random
var = ""
for i in range(6):
    num = str(random.randint(1,9))
    strs = chr(random.randint(65,90))
    chocie = random.choice([num,strs])
    # var = var + chocie
    var = "".join([var,chocie])
print(var,repr(var))

序列化

比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给?
现在我们能想到的方法就是存在文件里,然后另一个python程序再从文件里读出来。
但是我们都知道,对于文件来说是没有字典这个概念的,所以我们只能将数据转换成字典放到文件中。
你一定会问,将字典转换成一个字符串很简单,就是str(dic)就可以办到了,为什么我们还要学习序列化模块呢?
没错序列化的过程就是从dic 变成str(dic)的过程。现在你可以通过str(dic),将一个名为dic的字典转换成一个字符串,
但是你要怎么把一个字符串转换成字典呢?
聪明的你肯定想到了eval(),如果我们将一个字符串类型的字典str_dic传给eval,就会得到一个返回的字典类型了。
eval()函数十分强大,但是eval是做什么的?e官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。
BUT!强大的函数有代价。安全性是其最大的缺点。
想象一下,如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,那么后果实在不堪设设想。
而使用eval就要担这个风险。
所以,我们并不推荐用eval方法来进行反序列化操作(将str转换成python中的数据结构)
View Code

序列化的目的

1、以某种存储形式使自定义 对象持久化
2、将对象从一个地方传递到另一个地方。
3、使程序更具维护性。
json提供了四个功能:dumps、dump、loads、load
json:序列化集合时报错,序列化中的内容只能包含:字典 列表 数字 字符串,如果是元组——自动转成列表的样子
>>> import json
>>> dic = {'k1':'v1','k2':'v2','k3':'v3'}
>>> str_dic = json.dumps(dic)
>>> print(type(str_dic),str_dic)
<class 'str'> {"k1": "v1", "k2": "v2", "k3": "v3"}
>>> dic2 = json.loads(str_dic)
>>> print(type(dic2),dic2)
<class 'dict'> {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
>>> t1 = (1,2,3)
>>> str_dic = json.dumps(t1)#如果将元组序列化后,反序列化不能变成元组
>>> print(type(str_dic),str_dic)
<class 'str'> [1, 2, 3]
>>> dic2 = json.loads(str_dic)
>>> print(type(dic2),dic2)
<class 'list'> [1, 2, 3]
>>> t2= [1,2,3]
>>> str_dic = json.dumps(t2)
>>> print(type(str_dic),str_dic)
<class 'str'> [1, 2, 3]
>>> dic2 = json.loads(str_dic)
>>> print(type(dic2),dic2)
<class 'list'> [1, 2, 3]
>>> list_s = [1,['a','b','c'],3,{'k1':'v1','k2':'v2'}]#可以处理多类型
>>> str_dic = json.dumps(list_s)
>>> print(type(str_dic),str_dic)
<class 'str'> [1, ["a", "b", "c"], 3, {"k1": "v1", "k2": "v2"}]
>>> s = {1,3,4,5}#序列化列表时报错
>>> str_dic = json.dumps(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python36\lib\json\__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "C:\Python36\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "C:\Python36\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "C:\Python36\lib\json\encoder.py", line 180, in default
    o.__class__.__name__)
TypeError: Object of type 'set' is not JSON serializable

load &dump

load & dump 只是一次性的存读。

f = open("text.txt", 'a')
dic = {"k1":1}
tu = (123,[1,2,3],{"1":23})
json.dump(dic, f)
json.dump(tu, f)
f.close()
f = open("text.txt")
dic2 = json.load(f)
dic3 = json.load(f)
f.close()
print(dic2)
print(dic3)

pickle:

dic = {'k1':'v1','k2':'v2','k3':'v3'}#
str_pic = pickle.dumps(dic)  #序列化到内存(字符串格式保存)
# print(str_pic,type(str_pic))
dic2 = pickle.loads(str_pic)
print(dic2,type(dic2))
# str_time = time.localtime(1000000000)
# f = open("times.txt","wb")
# pickle.dump(str_time,f)
# f.close()
f = open("times.txt","rb")
str_time = pickle.load(f)
print(str_time.tm_year)

使用pickle 往文件夹中写内容

 with open("user_name.txt", 'ab') as f:
                str_name = pickle.dumps("%s" % (user_name + "|" + password + "|" + identity))
                f.write(str_name+b"\n")
                return True

 

既然pickle如此强大,为什么还要学json呢?json是一种所有的语言都可以识别的数据结构。

但是如果我们用pickle进行序列化,其他语言就不能读懂这是什么了~

shelve:

  引用shelve后,使用shelve打开文件shelve.open(),

f1 = shelve.open("shelve_file.txt")
# print(f1["key"])
f1["key"] = "this was not here before"
print(type(f1["key"]))#<class 'str'>
f1.close()

f1 = shelve.open("shelve_file.txt")
existing = f1["key"] #首先需要将读取的内容赋值给一个变量
f1.close()
print(existing)

f = shelve.open("shelve.txt",flag="r")#设置flag= “r”,代表只读,不支持多人同时写,但是可以同时读
tiems = f["key"]
f.close()
print(tiems)

#正常情况下shelve打开的文件句柄感知不到值的修改,设置writeback = True就可以保存修改内容了
import shelve
# f2 = shelve.open('shelve_file', writeback=True)
# print(f2['key'])
# f2['key']['new_value'] = {1,2,3}
# f2.close()
# import shelve
f = shelve.open('shelve_file',flag='r')
print(f['key'])
f.close()

 

f = shelve.open("shelve.txt",writeback=True)
ts = f["key"]
f.close()
print(ts)

writeback方式有优点也有缺点。优点是减少了我们出错的概率,并且让对象的持久化对用户更加的透明了;但这种方式并不是所有的情况下都需要,首先,使用writeback以后,shelf在open()的时候会增加额外的内存消耗,并且当DB在close()的时候会将缓存中的每一个对象都写入到DB,这也会带来额外的等待时间。因为shelve没有办法知道缓存中哪些对象修改了,哪些对象没有修改,因此所有的对象都会被写入。

 os模块:

os模块时与操作系统交互的一个接口

os.getcwd():获取当前路径

os.chdir("文件名"):移动文件路径

os.makedirs("name1/name2")递归生成多级目录,已存在报错,

os.removedirs("name"):  

os.removedirs(r"C:\Users\yanghu\PycharmProjects\s8\day21\name1\name2\name3")

os.mkdir("name1")#不可以重复创建

os.rmdir("name1")

os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
 
 
os.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录
os.stat('path/filename')  获取文件/目录信息
os.stat('path/filename')  获取文件/目录信息
os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep    输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n"
os.system("bash command")运行shell命令,直接显示
os.popen("文件"):
# os.system('dir')  #没有返回值,且直接执行代码,把结果直接输出
# ret = os.popen('dir')  #如果有结果就将结果返回回来
# print(ret.read())   #ret.read()获取结果
 
 

os.path

os.path.abspath(path) 返回path规范化的绝对路径 os.path.split(path) 将path分割成目录和文件名二元组返回 os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。
                        即os.path.split(path)的第二个元素
os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path)  如果path是绝对路径,返回True
os.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path)  返回path所指向的文件或者目录的最后访问时间
os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path) 返回path的大小


sys模块 与Python解释器的一个接口
sys.argv 命令行参数List,第一个元素是程序本身路径 
sys.exit(n) 退出程序,正常退出时exit(0),错误退出sys.exit(1)
sys.version 获取Python解释程序的版本信息
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
 

什么是模块?

 
 

里面含有Python定义和声明的模块,以.py后缀结尾的文件

 
 

为什么使用模块?

 
 

退出Python解释器,后之前定义的函数变量全部消失。因此我们将程序写到文件中永久保存,以Python test.py 运行程序。随着功能增加,不同文件存放不同程序,方便管理。同时也可以导入其他文件,实现程序的重复利用。

 
 

如何使用模块?

 
 

(1)模块中含有执行语句与函数,当模块名第一次遇到import时就会执行(import 可在程序的任意一个地方。为预防同一个模块多次导入,第一次执行导入时,模块名就已经加载到内存,后续import相同的模块名只是增加引用,而没有执行模块内的语句)

 
 

(2)每个模块有自己的命名空间,定义在模块中的函数,会把模块名称当做全局命名空间,这样当导入时,就不怕与自己的定义的函数名冲突。

 
 

(3)引入模块时做了三件事:(1)位模块名创建新的名称空间,若是引入的模块中有使用global 时,访问的就是这个命名空间。(2)在新创建的命名空间中运行改代码(3)创建名字my_module引用该命名空间(这个名字与变量是一致的,都是第一类。my_module.)

 
 

(4) 为模块名起别名:import my_modules as sm

 
 

常用模块:collection

 
 

(1)namedtuple("potion",["x","y"]):返回一个带有命名字段的元组,通过对象属性的名字就可以找到相应的值

 
 
>>> point = namedtuple("point",['x','y']) >>> point.__doc__ 'point(x, y)' >>> p= point(1,3) >>> p[0] 1 >>> p.x 1 >>> p.y 3 >>> x,y = p >>> x,y (1, 3) >>>
 
 

(2)queue:队列,先进先出,可以存放任何数据类型,put,get,put ,其中get起到hold的功能,get_nowait 没有不会hold,切会报错。

 
 

(3)dqueue:队列可以两端存放,可存放任何类型。使用append,appendleft,取出元素使用pop,popleft

 
 

(4)orderdict:可以创建有序的字典

 
 
dic = OrderedDict([(1,2),("NAME",2)])
for k in dic: print(k,dic[k])
 
 

(5)default_factory

 
 
# from collections import defaultdict
# def func():
# return 0 # my_dict = defaultdict(func) # # my_dict = {} # print(my_dict['k'])
 
 

 

 
 

 

 
 

Re模块

 
 

正则是什么?

 
 

  正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法。或者说:正则就是用来描述一类事物的规则。(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。

 
 

通用、处理字符串---贪婪匹配

 
 

意义:正则表达式,正则是一种处理文字的规则,给我们提供一些规则,让我们从杂乱无章的文字中提取有效信息。

 
 

模块?

 
 

生活中已经存在,为了解决生活、科技世界里实际要解决的问题。比如time模块已经存在,Python拿过来可以直接使用。

 
 

Re--模块 ,该模块可以更好的帮助你从字符串的处理和检查用户输入的信息。

 
 

基础

 
 

  官方定义:正则表达式是对字符串的操作的一种逻辑公式,事先规定好一些特定字符,及这些字符的特定组合,组成一个“规则字符串”,利用组成的“规则字符串”实现对文本的过滤。

 
 

字符串在电脑上显示是有位置存在的,就像通过索引可以找到指定位置的字符串。而正则,可以分辨出所在位置出现的字符串是否合法。同样同一个位置除了指定特定的字符串还可以扩大范围,如:同一个位置可以出现0,也可以出现1。。。其他数字,在不确定出现哪些数字的情况下,可以指定范围,而“[1,2,3,4]”

 
 

中括号内部的数字,代表这个位置有可能出现1,2,3,4,中括号则被称为字符组。

 
 

字符组的示例:数字:[1,2,3,4,5],字母:[a-z],数字字母组合:[1-9a-zA-F]

 
 
字符组
 
 

正则表达式同样使用字符串表示,如何使用字符描述字符?

 
 

"\d"可以匹配数字,“\w”表示字符、数字、下划线

 
 

“00\d”可以匹配“006”但是匹配不了“00a”

 
 

“\d\d\d”可以匹配123

 
 

“\w\w\d“可以匹配“py3”

 
 

“ . ”英文符号点,可以表示任意字符(\n)除外

 
 

“ py.”可以匹配任意字符“pyc”,“pyj”,"pyy"

 
 

 
 

 

 
 

常用的元字符:

 
 
元字符匹配内容
.匹配除换行符任意字符
\w匹配任意字母数字下划线
\d 匹配任意数字
\s匹配任意空白符
\n匹配一个换行符
\t 匹配一个制表符
\b匹配一个单词的结尾
^匹配字符串的开始
$匹配字符串的结尾
\W匹配非字母数字下划线
\D匹配非数字
\S 匹配非空格
a|b匹配a字符或b字符
()表示一个组
[....]匹配字符中的字符
[^...]匹配除了字符组中的所用字符
 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

量词约束字符用的。

 
 
量词用法说明
* 重复零次或多次
+重复一次或多次
重复零次或一次
{n}重复n次
{n,}重复n次或更多次
{n,m}重复n到m次
 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

分组()和 |, [^....]

 
 

身份证号码是一个长度为15或18个字符的字符串,如果是15位则全部?️数字组成,首位不能为0;如果是18位,则前17位全部是数字,末位可能是数字或x,下面我们尝试用正则来表示:

 
 

第一种:^[1-9]\d{14}(\d{2}[1-9x])?$

 
 

 
 

 

 
 

第二种:

 
 

在量词后面加上“?”表示费贪婪模式

 
 

正则匹配:字符 量词 非贪婪匹配

 
 

  字符、字符组、元字符、表示一个位置出现的内容

 
 

 

 
 

转义字符

 
 

python中:
1. '\n'是用来换行的
2. '\\n'是正则用来匹配换行的
因为python无法直接解释带'\'的,需要吧'\'转译,可以在字符串前加r,来取消实际的意义
所以'\n'需要使用r'\n','\\n'需要使用r'\\n'来变成普通的字符串

 
 

 
 

 

 
 

 

 
 

贪婪匹配

 
 

 
 

  定义:在满足匹配时,匹配尽可能长的字符串,默认情况下使用贪婪匹配

 
 

  <.*> -----><script>......<script>,全部会匹配上

 
 

  <.*?> -----<script>......<script>,加上?改为非贪婪模式,匹配尽量短的字符串

 
 
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
 
 
取尽量少的任意字符,一般不会这么单独写,他大多用在:
 
 
.*?的用法
 
 
. 是任意字符
* 是取 0 至 无限长度
? 是非贪婪模式。
何在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在:
.*?x

就是取前面任意长度的字符,直到一个x出现
 
 
匹配非数字有三种方式:[^\d]、[^0-9]、\D
\D:匹配除了数字之外的所有字符匹配空格、标点符号(引号、连字符、反斜杠、方括号)
等字符
\w:只会匹配字母数字下划线
\f 换页符
\h 水平空白符
\H 非水平空白符
\v 垂直制表符
\V 非垂直制表符
 
 

findall():找不到返回空的列表。找到所有的结果放到列表中,返回该列表,分组优先,优先先显示

 
 
ret = re.findall("www.(baidu|odboy).com","www.baidu.com") print(ret) ['baidu']#findall,正则有元组,优先返回元组,
ret = re.findall("www.(?:baidu|odboy).com","www.baidu.com")#使用?:取消元组优先
print(ret)
['www.baidu.com']
 
 
 

 

 
 

search:从左至右依次找,找到就返回,但是需要使用group()获取返回值,re.search(),找不到返回None,使用group()报错

 
 

match():从头开始匹配,匹配不上返回None,匹配上使用group()获取返回值。

 
 

re.split("[ab]","abcd")根据正则切割,如果是分组

 
 
ret = re.split('(\d+)',"eva3egon4yuan")#不会把数字切割,以元组为准
 
 

 

 
 

re.sub()根据正则去替换

 
 

re.sub 有三个必填参数:pattern ,repl,string  两个选填count flage

 
 

  pattern:正则中的模式字符串、  

 
 

       注意:

 
 

          反斜杠加数字 (\N))对应着匹配的组(matched group),

 
 

            ——\6,代表pattern re模式字符串中的第六个数组,意味着待匹配的字符串中有对应数组,

 
 

比如,想要处理:

 
 
hello crifan, nihao crifan
 
 

且此处的,前后的crifan,肯定是一样的。

 
 

而想要把整个这样的字符串,换成crifanli

 
 

则就可以这样的re.sub实现替换:

 
 

  

 
 
inputStr = "hello crifan, nihao crifan";
replacedStr = re.sub(r"hello (\w+), nihao \1", "crifanli", inputStr); print "replacedStr=",replacedStr; #crifanli
 
 

re.subn():

 
 

compile()编译正则

 
 

finditer():找所有,返回迭代器,取值for 结果需group

 
 

re模块下的常用方法

 
 

 

 
 
import re

ret = re.findall('a', 'eva egon yuan') # 返回所有满足匹配条件的结果,放在列表里 print(ret) #结果 : ['a', 'a']  ret = re.search('a', 'eva egon yuan').group() print(ret) #结果 : 'a' # 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以 # 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。  ret = re.match('a', 'abc').group() # 同search,不过尽在字符串开始处进行匹配 print(ret) #结果 : 'a'  ret = re.split('[ab]', 'abcd') # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割 print(ret) # ['', '', 'cd']  ret = re.sub('\d', 'H', 'eva3egon4yuan4', 1)#将数字替换成'H',参数1表示只替换1个 print(ret) #evaHegon4yuan4  ret = re.subn('\d', 'H', 'eva3egon4yuan4')#将数字替换成'H',返回元组(替换的结果,替换了多少次) print(ret) obj = re.compile('\d{3}') #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字 ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串 print(ret.group()) #结果 : 123 import re ret = re.finditer('\d', 'ds3sy4784a') #finditer返回一个存放匹配结果的迭代器 print(ret) # <callable_iterator object at 0x10195f940> print(next(ret).group()) #查看第一个结果 print(next(ret).group()) #查看第二个结果 print([i.group() for i in ret]) #查看剩余的左右结果
 
 

注意:

 
 

1 findall的优先级查询:

 
 
import re

ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com') print(ret) # ['oldboy'] 这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可  ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com') print(ret) # ['www.oldboy.com']
 
 

2 split的优先级查询

 
 
ret=re.split("\d+","eva3egon4yuan") print(ret) #结果 : ['eva', 'egon', 'yuan']  ret=re.split("(\d+)","eva3egon4yuan") print(ret) #结果 : ['eva', '3', 'egon', '4', 'yuan'] #在匹配部分加上()之后所切出的结果是不同的, #没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项, #这个在某些需要保留匹配部分的使用过程是非常重要的。
 
 
 
 
 
 
 
 
 

 

转载于:https://www.cnblogs.com/huyangblog/p/7841090.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值