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))



序列化




pycharm 查看 docker_操作系统

pycharm 查看 docker_操作系统_02

比如,我们在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


序列化的目的


 


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]





pycharm 查看 docker_操作系统

字符组

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


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


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


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


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


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


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


pycharm 查看 docker_json_04


 


常用的元字符:


元字符

匹配内容

.

匹配除换行符任意字符

\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])?$


pycharm 查看 docker_操作系统_05


 


第二种:


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


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


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

 

pycharm 查看 docker_pycharm 查看 docker_06


转义字符


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


pycharm 查看 docker_pycharm 查看 docker_07


 


 


贪婪匹配


pycharm 查看 docker_python_08


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


  <.*> -----><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'] #在匹配部分加上()之后所切出的结果是不同的, #没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项, #这个在某些需要保留匹配部分的使用过程是非常重要的。