前期回顾:
无
本期内容:
一、atm作业讲解二、递归的例子,阶乘三、反射四、模块五、冒泡算法六、本周作业
一、ATM作业讲解
二、递归的例子,阶乘
使用递归实现“1*2*3*4*5*6*7”
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 递归阶乘
def func(num):
if num == 1:
return 1
return num * func(num-1)
x = func(7)
print(x)
三、反射
利用字符串的形式去对象(模块)中操作(寻找)成员,反射实例:伪造WEB框架的路由系统反射:基于字符串的形式去对象(模块)中操作成员
# 反射的四个方法
getattr(commons,input) # 获取
hasattr(commons,input) # 检查
setattr(commons,input) # 设置
delattr(commons,input) # 删除
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# index 反射主程序
import commons
def run():
inp = input('请输入要打开页面的URL: ')
if hasattr(commons,inp):
func = getattr(commons,inp)
func()
else:
print('404')
if __name__ == __name__:
run()
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# commons index 调用的模块
def login():
print('登录页面')
def logout():
print('退出页面')
def home():
print('主页面')
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 反射
# index.py
def run():
inp = input('请输入要打开页面的URL: ')
m,f = inp.split('/')
obj = __import__(m) # 以字符串格式导入模块
if hasattr(obj,f):
func = getattr(obj,f)
func()
else:
print('404')
if __name__ == __name__:
run()
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# commons.py
def login():
print('登录页面')
def logout():
print('退出页面')
def home():
print('主页面')
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# manager.py
def manager():
print('管理页面')
obj = __import__("lib."+m , formlist=True)
扩展:导入模块
import xxxform xxx import oooobj = __import__("xxx")obj = __import__("xxx.ooo.xxx",formlist=True)
四、模块
loggingtime/datetimejson/picklerequests
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'
os.system("bash command") 运行shell命令,直接显示
os.environ 获取系统环境变量
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所指向的文件或者目录的最后修改时间
sys
用于提供对Python解释器相关的操作:
sys.argv 命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit(0)
sys.version 获取Python解释程序的版本信息
sys.maxint 最大的Int值
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
sys.stdin 输入相关
sys.stdout 输出相关
sys.stderror 错误相关
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 模块
import os
import sys
ss = os.path.abspath(__file__) # 获取文件的绝对路径
dd = os.path.dirname(__file__) # 获取文件的所在目录
sys.path.append(os.path.dirname(os.path.abspath(__file__))) # 将文件的目录添加到系统默认路径
hashlib
用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
import hashlib
# ######## md5 ########
hash = hashlib.md5()
# help(hash.update)
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())
print(hash.digest())
######## sha1 ########
hash = hashlib.sha1()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())
# ######## sha256 ########
hash = hashlib.sha256()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())
# ######## sha384 ########
hash = hashlib.sha384()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())
# ######## sha512 ########
hash = hashlib.sha512()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())
以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。
import hashlib
# ######## md5 ########
hash = hashlib.md5(bytes('898oaFs09f',encoding="utf-8"))
hash.update(bytes('admin',encoding="utf-8"))
print(hash.hexdigest())
python内置还有一个 hmac 模块,它内部对我们创建 key 和 内容 进行进一步的处理然后再加密
import hmac
h = hmac.new(bytes('898oaFs09f',encoding="utf-8"))
h.update(bytes('admin',encoding="utf-8"))
print(h.hexdigest())
MD5
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# MD5 加密
import hashlib
obj = hashlib.md5()
obj.update(bytes('123',encoding='utf-8'))
result = obj.hexdigest()
print(result)
正则表达式
re模块
普通字符:a-z/A-Z/0-9
元字符: . ^ $ * + ? {} [] | ()
字符:
. 匹配除换行符以外的任意字符
w 匹配字母或数字或下划线或汉字
s 匹配任意的空白符
d 匹配数字
匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束
次数:
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
re.findall() # 匹配所有结果
# findall,获取非重复的匹配列表;如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果模型中有多个组,则以列表形式返回,且每一个匹配均是元祖;
# 空的匹配也会包含在结果中
#findall(pattern, string, flags=0)
# 无分组
r = re.findall("aw+",origin)
print(r)
# 有分组
origin = "hello alex bcd abcd lge acd 19"
r = re.findall("a((w*)c)(d)", origin)
print(r)
re.match() # 从起始位置开始匹配
# match,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None
match(pattern, string, flags=0)
# pattern: 正则模型
# string : 要匹配的字符串
# falgs : 匹配模式
X VERBOSE Ignore whitespace and comments for nicer looking RE's.
I IGNORECASE Perform case-insensitive matching.
M MULTILINE "^" matches the beginning of lines (after a newline)
as well as the string.
"$" matches the end of lines (before a newline) as well
as the end of the string.
S DOTALL "." matches any character at all, including the newline.
A ASCII For string patterns, make w, W, , B, d, D
match the corresponding ASCII character categories
(rather than the whole Unicode categories, which is the
default).
For bytes patterns, this flag is the only available
behaviour and needn't be specified.
L LOCALE Make w, W, , B, dependent on the current locale.
U UNICODE For compatibility only. Ignored for string patterns (it
is the default), and forbidden for bytes patterns.
# 无分组
r = re.match("hw+", origin)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果
print(r.groupdict()) # 获取模型中匹配到的分组结果
# 有分组
# 为何要有分组?提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来)
r = re.match("h(w+).*(?P<name>d)$", origin)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果
print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组
re.search() # 匹配一个结果
# search,浏览整个字符串去匹配第一个,未匹配成功返回None
# search(pattern, string, flags=0)
# 无分组
r = re.search("aw+", origin)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果
print(r.groupdict()) # 获取模型中匹配到的分组结果
# 有分组
r = re.search("a(w+).*(?P<name>d)$", origin)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果
print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组
re.sub() # 匹配替换
# sub,替换匹配成功的指定位置字符串
sub(pattern, repl, string, count=0, flags=0)
# pattern: 正则模型
# repl : 要替换的字符串或可执行对象
# string : 要匹配的字符串
# count : 指定匹配个数
# flags : 匹配模式
# 与分组无关
origin = "hello alex bcd alex lge alex acd 19"
r = re.sub("aw+", "999", origin, 2)
print(r)
re.split() # 分割
# split,根据正则匹配分割字符串
split(pattern, string, maxsplit=0, flags=0)
# pattern: 正则模型
# string : 要匹配的字符串
# maxsplit:指定分割个数
# flags : 匹配模式
# 无分组
origin = "hello alex bcd alex lge alex acd 19"
r = re.split("alex", origin, 1)
print(r)
# 有分组
origin = "hello alex bcd alex lge alex acd 19"
r1 = re.split("(alex)", origin, 1)
print(r1)
r2 = re.split("(al(ex))", origin, 1)
print(r2)
进度条小练习
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 进度条小程序
import sys
import time
def view_bar(num, total):
rate = float(num) / float(total)
rate_num = int(rate * 100)
r = ' %s%d%%' % ("="*num , rate_num)
sys.stdout.write(r)
sys.stdout.flush()
if __name__ == '__main__':
for i in range(0, 101):
time.sleep(0.1)
view_bar(i, 100)
五、冒泡算法
#!/usr/bin/env python
# -.- coding: utf-8 -.-
# By sandler
# 冒泡排序
li = [1,5,2,7,11,44,66,33,22]
print(li)
for i in range(len(li))[::-1]:
for j in range(i):
if li[j] > li[j+1]:
li[j],li[j+1] = li[j+1], li[j]
print(li)
# 执行结果
[1, 5, 2, 7, 11, 44, 66, 33, 22]
[1, 2, 5, 7, 11, 22, 33, 44, 66]
六、本周作业:
计算器,只处理加减乘除
8*12+(6-(5*6-2)/77+2)*(3-7)+8
# 1、从前到后找,找到第一个 (开始 )结尾,中间不含有括号
# 2、(中间不包含括号)
def 处理加减乘除(表达式):
# 8*12+1*4+8
return 1
def 处理括号(表达式):
while True:
#8*12+(6-(5*6-2)/77+2)*(3-7)+8
re.split("((中间不包含括号))", 表达式, 1)
8*12+(6- 5*6-2 /77+2)*(3-7)+8
ret = 处理加减乘除(5*6-2 )
8*12+(6- ret /77+2)*(3-7)+8