前提:dir,__all__,help,__doc__,__file__
dir:可以用来查看模块中的所有特性(函数,类,变量等)
>>> import copy >>> dir(copy) ['Error', 'PyStringMap', '_EmptyClass', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_c opy_dispatch', '_copy_immutable', '_copy_with_constructor', '_copy_with_copy_met hod', '_deepcopy_atomic', '_deepcopy_dict', '_deepcopy_dispatch', '_deepcopy_lis t', '_deepcopy_method', '_deepcopy_tuple', '_keep_alive', '_reconstruct', 'built ins', 'copy', 'deepcopy', 'dispatch_table', 'error', 'name', 't', 'weakref'] >>> [x for x in dir(copy) if not x.startswith('_')] ['Error', 'PyStringMap', 'builtins', 'copy', 'deepcopy', 'dispatch_table', 'erro r', 'name', 't', 'weakref']
__all__:(dir中有这个变量)这个变量中包含了一个列表。和我们使用dir加上列表推导式相似。
>>> copy.__all__ ['Error', 'copy', 'deepcopy']
他定义了模块的公有接口,或者说他告诉解释器当我们使用
from copy import *
时,会导入模块的那些函数方法。__all__在编写模块是,可以过滤掉大多不需要的函数方法。若是没有__all__,使用import *会将除了以下划线开头的所有全局名称导入
help:获取帮助,提供日常需要的信息
>>> help(copy) Help on module copy: NAME copy - Generic (shallow and deep) copying operations. DESCRIPTION Interface summary: .... >>> help(copy.copy) Help on function copy in module copy: copy(x) Shallow copy operation on arbitrary Python objects. See the module's __doc__ string for more info.
引用了__doc__特性,事实上是使用了文档字符串(写在模块开头,或者函数开头的)
__file__:获取文件位置:便于查看文件源代码位置:
>>> copy.__file__ 'C:\Users\Administrator\AppData\Local\Programs\Python\Python35\lib\copy .py'
一.sys
sys.argv 命令行参数List,第一个元素是程序本身路径
import sys args = sys.argv[1:] #默认0是程序名 args.reverse() print(','.join(args)) D:MyPythonday24基础回顾 1装饰器>python test.py ag1 ag2 ag3 ag3,ag2,ag1
sys.exit(n) 退出程序,正常退出时exit(0)
>>> import sys
>>> sys.exit()
sys.version 获取Python解释程序的版本信息 #python --version
>>> sys.version '3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)]'
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
>>> sys.path ['', 'C:\Users\Administrator\AppData\Local\Programs\Python\Python35\pyth on35.zip', 'C:\Users\Administrator\AppData\Local\Programs\Python\Python35 \DLLs', 'C:\Users\Administrator\AppData\Local\Programs\Python\Python35\ lib', 'C:\Users\Administrator\AppData\Local\Programs\Python\Python35', 'C :\Users\Administrator\AppData\Local\Programs\Python\Python35\lib\site-p ackages']
sys.platform 返回操作系统平台名称
>>> sys.platform 'win32'
sys.stdin 输入相关 有读取属性r 从屏幕中读取
>>> var = sys.stdin.read() aasddsa ^Z >>> var 'aasddsa ' >>> var = sys.stdin.read(5) dsad >>> var 'dsad ' >>>
sys.stdout 输出相关 有写入属性w 向屏幕中写入
>>> sys.stdout.write('dasf') dasf4 >>> sys.stdout.flush() #刷新当前屏幕 shell中无用
sys.stderror 错误相关 有写入属性w 向屏幕写入(会含有输出错误信息的信息长度)
print(sys.stderr) print(sys.stderr.write("errfawfa")) <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'> 8 errfawfa
二,os
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd os.curdir 返回当前目录: ('.') os.pardir 获取当前目录的父目录字符串名:('..') os.makedirs('dir1/dir2') 可生成多层递归目录 os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 os.remove() 删除一个文件 os.rename("oldname","new") 重命名文件/目录 os.stat('path/filename') 获取文件/目录信息 os.sep 操作系统特定的路径分隔符,win下为"\",Linux下为"/" os.linesep 当前平台使用的行终止符,win下为" ",Linux下为" " os.pathsep 用于分割文件路径的字符串 os.name 字符串指示当前使用平台。win->'nt'; Linux->'posix'
>>> sys.platform 'win32' >>> os.name 'nt'
os.system("bash command") 运行shell命令,直接显示。用于运行外部程序
>>> os.system('ls -al') total 50565
os.environ 获取系统环境变量 在系统中高级环境变量Path设置中的数据
os.path.abspath(path) 返回path规范化的绝对路径
os.path.split(path) 将path分割成目录和文件名二元组返回
os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素,就是返回上级目录
>>> os.path.dirname("c:/sys") 'c:/' >>> os.path.dirname("c:/sys/windows/1.txt") 'c:/sys/windows'
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所指向的文件或者目录的最后修改时间 是时间戳
三:random
该模块包括返回随机数的函数。可以用于模拟或者产生随机输出的程序。
>>> random.__all__ ['Random', 'seed', 'random', 'uniform', 'randint', 'choice', 'sample', 'randrang e', 'shuffle', 'normalvariate', 'lognormvariate', 'expovariate', 'vonmisesvariat e', 'gammavariate', 'triangular', 'gauss', 'betavariate', 'paretovariate', 'weib ullvariate', 'getstate', 'setstate', 'getrandbits', 'SystemRandom']
注意:事实上,所产生的数字都是伪随机数,也就是说他们看起来是完全随机的,实际上,他们是以一个可预测的系统作为基础。不过,已经很不错了。若是想实现真正的随机可以使用os中的urandom或者random中的SystemRandom
>>> random.random() #返回一个在0-之间的随机数 0.5134022843262868 >>> help(random.random) Help on built-in function random: random(...) method of random.Random instance random() -> x in the interval [0, 1). >>> random.randint(1,100) #返回一个在1,100之间的整数 20 >>> random.randrange(1,100) 80
四:hashlib
用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
import hashlib
######### md5 ########
h2 = hashlib.md5() h2.update(bytes('123456', encoding='utf-8')) print(h2.hexdigest()) #是字符串十六进制 print(h2.digest()) #是字节byte型 通过.hex()可以转换为上面的字符串十六进制
补充:
digest()
>>> help(hashlib._hashlib.HASH.digest) Help on method_descriptor: digest(...) Return the digest value as a string of binary data. 返回一个bytes 八位一字节(ASCII),对于(编码的字符,若是ASCII中字符则直接显示,否则按照编码进行转换)
b'xeaHWo0xbex16ix97x16x99xc0x9axd0\x94'
对于bytes编码的字符,若是ASCII中字符则直接显示,否则按照编码进行转换
>>> b = bytes("a",encoding="utf-8") >>> b b'a' >>> b = bytes("a你",encoding="utf-8") >>> b b'axe4xbdxa0'
hexdigest()
>>> help(hashlib._hashlib.HASH.hexdigest) Help on method_descriptor: hexdigest(...) Return the digest value as a string of hexadecimal digits. 返回一个十六进制字符串str类型
'ea48576f30be1669971699c09ad05c94'
-------------------------------------------------------------------------------------
digest()转hexdigest()
>>> h2.digest().hex()
-------------------------------------------------------------------------------------
hexdigest()转digest()
需要使用binascii模块
>>> help(binascii) Help on built-in module binascii: NAME binascii - Conversion between binary data and ASCII
用于转换 --- 在二进制和ASCII码之间
binascii中a2b_hex
>>> help(binascii.a2b_hex) Help on built-in function a2b_hex in module binascii: a2b_hex(hexstr, /) Binary data of hexadecimal representation.
将十六进制字符串转化为二进制用bytes类型显示(ASCII) hexstr must contain an even number of hex digits (upper or lower case). This function is also available as "unhexlify()".
其中十六进制必须是偶数
一般我们直接使用十六进制字符串,直接是32位字符串
转换成功:
>>> binascii.a2b_hex(h2.hexdigest()) b'xeaHWo0xbex16ix97x16x99xc0x9axd0\x94' >>> h2.digest() b'xeaHWo0xbex16ix97x16x99xc0x9axd0\x94' >>> h2.hexdigest() 'ea48576f30be1669971699c09ad05c94' >>> binascii.a2b_hex(h2.hexdigest()) b'xeaHWo0xbex16ix97x16x99xc0x9axd0\x94'
-------------------------------------------------------------------------------------
其中md5算法时不能被反解的,但是可以被撞库,获取密码。
更加安全的方法是在加密算法中添加自定义key再来进行加密:
没有key时:
>>> h1 = hashlib.md5(bytes("123456",encoding="utf-8")) >>> h1.hexdigest() 'e10adc3949ba59abbe56e057f20f883e'
上面的数据很容易被撞库获取出来密码。尤其是这些简单的
-------------------------------------------------------------------------------------
使用自定义key时
>>> h2 = hashlib.md5(bytes("asd",encoding="utf-8")) >>> h2.update(bytes("123456",encoding="utf-8")) >>> h2.hexdigest() '1e55dbf412cb74d5e2c21fb6452408c7'
相当于使用两次update:
>>> h3 = hashlib.md5() >>> h3.update(byte("asd",encoding="utf-8")) >>> h3.update(bytes("123456",encoding="utf-8")) >>> h3.hexdigest() '1e55dbf412cb74d5e2c21fb6452408c7'
-------------------------------------------------------------------------------------
######## sha1 ########(这些算法的使用和md5相似)
h = hashlib.sha1() h.update(bytes('123456', encoding='utf-8')) print(h.hexdigest())
SHA1, SHA224, SHA256, SHA384, SHA512使用时一样的
-------------------------------------------------------------------------------------
python内置还有一个 hmac 模块,它内部对我们创建 key 和 内容 进行进一步的处理然后再加密
import hmac h = hmac.new(bytes('asd',encoding="utf-8")) h.update(bytes('123456',encoding="utf-8")) print(h.hexdigest())
#548b23c538c78d7053e3231919f78f36 与上面自定义key得出的密码不一样,说明在内部对key和内容又进行了处理
五:re正则模块
基础了解:正则表达式了解
(一)re模块中一些重要函数:
compile:根据原来包含正则表达式的字符串创建模式对象
函数re.compile将正则表达式(以字符串书写的)转换为模式对象,可以实现更加有效率的匹配。在调用search或者match函数的时候使用字符串正则表达式,他们也会在内部将正则表达式字符串转换为对象。与其每一次调用匹配时都去进行转换,不如在开始创建正则表达式时就使用对象,使用compile完成一次转换,后面就不需要转换。(调用方式也由re.search(正则字符串,匹配数据)----->正则对象.search(匹配数据))、
import fileinput, re pat = re.compile('Form: (.*) <.*?>$') #*、+限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个?就可以实现非贪婪或最小匹配。 for line in fileinput.input(): m = pat.search(line) if m: print(m.group(1))
search:在字符串中寻找模式(浏览整个字符串去匹配第一个)
函数re.search会在给定的字符串中(浏览整个字符串去匹配第一个)寻找第一个匹配的字符串。一旦找到,返回匹配对象,否则为空
>>> import re >>> pat = re.compile("<(.*)>") >>> st = "a email from <ld@qq.com>" >>> ret = pat.search(st) >>> ret <_sre.SRE_Match object; span=(13, 24), match='<ld@qq.com>'>
否则为空:
>>> st2 = "a email from ld@qq.com" >>> ret2 = pat.search(st2) >>> ret2 >>>
匹配第一个:
pat2 = re.compile(r"**(.+?)**") st = "**this** is **book**" res = pat2.search(st) #只会匹配出第一个,然后不再继续向后匹配--->只会匹配出 **this** print(res.group(0)) #**this** print(res.group(1)) #this
#向下则全部会报错:因为只匹配到第一组,只有0和1索引 #Traceback (most recent call last): # File "D:/MyPython/day24/基础回顾/01装饰器/test.py", line #59, in <module> # print(res.group(2)) #IndexError: no such group print(res.group(2)) print(res.group(3))
注意:findall会匹配所有,sub会替换所有匹配项
match:从起始位置开始匹配(只是从字符串开头开始匹配),匹配成功返回一个对象,未匹配成功返回None
import re st = 'a email from <ld@qq.com>' pat = re.compile("<(.*)>") ret3 = pat.match(st) print(ret3) #None 因为字符串开头没有匹配到 st = '<ld@qq.com> a email from ' pat = re.compile("<(.*)>") ret3 = pat.match(st) #匹配数据出现在开头,才能够被匹配 print(ret3) #<_sre.SRE_Match object; span=(0, 11), match='<ld@qq.com>'>
split:会根据模式的匹配项来分割字符串。类似于字符串的split
some_text = "alpha, fawfgwa,,,,,fwafaw fwafaaaa" pat = re.compile('[, ]+') #[] 中括号中的任意数据 ret = pat.split(some_text) print(ret) #['alpha', 'fawfgwa', 'fwafaw', 'fwafaaaa']
findall:以列表形式返回给定模式的所有匹配项
some_text = "[faw非f]服务[wfw发a]adawf[你faw]" pat = re.compile('[(.*?)]') #记得取消贪婪模式*和+后面加上? ret = pat.findall(some_text) print(ret) #['faw非f', 'wfw发a', '你faw']
sub:替换匹配成功项的数据(含有替换字符串,替换个数)(相比于字符串replace来说查找更加灵活,替换也方便)
some_text = "[faw非f]服务[wfw发a]adawf[你faw]" pat = re.compile('faw') #记得取消贪婪模式*和+后面加上? ret = pat.sub(" haha ",some_text,2) print(ret) #[ haha 非f]服务[wfw发a]adawf[你 haha ]
escape(string):将字符串中所有条数的正则表达式字符转义(实用|用处不大)
some_text = ". *+?" ret = re.escape(some_text) print(ret) #\. *+?
(二)匹配对象和组
首先了解一下什么是“组”:
我们所定义的匹配模式中,放在圆括号中的子模式就是组(单独的一个组,详细理解看补充中的栗子)。默认组0是我们整个匹配模式。其他的组号判断,一句他左侧的括号数
st = "https://www.baidu.com" pat = re.compile("https://((.*?).(.*?).(.*))")
#注意不要在这个匹配模式最后小括号中加上?取消贪婪模式,会出错,贪婪模式需要找到下一个界限(这里设置的是.)在哪,才会去获取到自己的边界。但是这里到最后就结束了,并没有找到下一个边界,所以不会匹配到最后一个
https://((www).(baidu).(com)) 组0:https://www.baidu.com 组1:www.baidu.com 组2:www 组3:baidu 组4:com
匹配对象的重要方法:
group:获取给定子模式(组)的匹配项(若没有给出组号,默认为0.而且我们只能使用99个组(除0外),即1-99)
st = 'https://www.baidu.com' pat = re.compile("https://((.*?).(.*?).(.*))") ret3 = pat.search(st) print(ret3) #<_sre.SRE_Match object; span=(0, 21), match='https://www.baidu.com'> print(ret3.group(0)) #https://www.baidu.com print(ret3.group(1)) #www.baidu.com print(ret3.group(2)) #www print(ret3.group(3)) #baidu print(ret3.group(4)) #com
start:获取给定组的开始位置
end:获取给定组的结束位置
span:获取一个组的开始和结束位置
st = 'https://www.baidu.com' pat = re.compile("https://((.*?).(.*?).(.*))") ret3 = pat.search(st) print(ret3.group(2)) #www print(ret3.span(2)) #(8, 11) print(ret3.start(2)) #8 print(ret3.end(2)) #11
补充:组和sub
多用于页面模板渲染等。可以按照组号进行替换
st = 'https://www.baidu.com' pat = re.compile("https://((.*?).(.*?).(.*))") ret = pat.sub(r"<h1>4</h1>",st) # ret = re.sub(pat,r'<h1>4</h1>',st) print(ret) #只返回了替换组号的数据<h1>com</h1>
注意:上面出现的情况是因为:
sub函数进行替换时:
sub(pat,repl,string)是使用repl将pat中匹配模式字符串全部替换,而我们这里pat就是 https://((.*?).(.*?).(.*)) ------ https://www.baidu.com,而repl就是我们获取的 <h1>com</h1>,所以替换出了问题
这里顺便再举一个栗子,让我们好好重新了解一下什么是组:
pat2 = re.compile(r"**(.+?)**") st = "**this** is **book**" ret = pat2.sub(r'<em>1</em>',st)
#注意:sub会将所有pat的匹配项进行替换 **this** 和 **book** 都是符合我们pat匹配模式的匹配项。他们每一个都是一个单独的组,都有自己的组号
#而这里使用1是去匹配了每一个组的组号为1的数据,都进行了替换(而且替换是将组中的数据都进行替换) #将**this** --> <em>this</em>
#将**book** --> <em>book</em>
相当于将组0替换为我们想要的数据(这里我们想要注意,不能对组0进行替换操作,像<em>