冒泡排序算法的原理以下:(从后往前) 1.比较相邻的元素。若是第一个比第二个大,就交换他们两个。 2.对每一对相邻元素做一样的工做,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。 3.针对全部的元素重复以上的步骤,除了最后一个。 4.持续每次对愈来愈少的元素重复上面的步骤,直到没有任何一对数字须要比较。
冒泡算法初级代码以下:python
1 ##冒泡 2 a=[9,2,1,55,33] 3 4 for i in range(len(a)): 5 for j in range(len(a)-1): 6 if a[j] > a[j+1]: 7 middle = a[j] 8 a[j] = a[j+1] 9 a[j+1] = middle 10 else: 11 pass 12 13 print(a)
执行结果以下:web
[1, 2, 9, 33, 55]
代码剖析:开始执行:初始列表a=[9,2,1,55,33],第一次外层循环i=0;第一次内层循环j=0;假如a[0]:9 > a[1]:2,交换位置,a[0]:2;a[1]:9,第二次内层循环j=1;假如a[1]:9 > a[2]:1,交换位置,第三次内层循环j=2;假如a[2]:9 > a[3]:55,不成立;pass,第四次内层循环j=3;假如a[3]:55 > a[4]:33,交换位置,内层循环结束,获得结果a[4]==55,拿到第一大的值。第二次外层循环i=1;第一次内存循环j=0;假如a[0]:2 > a[1]:1,交换位置,第二次内层循环j=1;假如a[1]:2 > a[2]:9,不成立,pass,第三次内层循环j=2;假如a[2]:9> a[3]:33,不成立,pass,第四次内层循环j=3;假如a[3]:33 > a[4]:55,不成立,pass,拿到结果a[3] ==33,拿到第二大的值,以此类推。一个一个像冒泡同样拿到最终的列表。正则表达式
选择排序(Selection sort)是一种简单直观的排序算法。它的工做原理以下:
首先在未排序序列中找到最小元素,存放到排序序列的起始位置,而后,再从剩余未排序元素中继续寻找最小元素,而后放到排序序列末尾。以此类推,直到全部元素均排序完毕。
选择排序初级代码以下:算法
##选择 b = [8,2,1,55,33] num = len(b)-1 for i in range(len(b)): index = 0 for j in range(num): if b[index] > b[j+1]: pass else: index = j+1 middle = b[num] b[num] = b[index] b[index] = middle num -= 1 print(b)
执行结果以下:shell
[1, 2, 8, 33, 55]
代码剖析:开始执行:num==4;第一次外部循环i=0;index=0;第一次内部循环;j=0;假如b[0]:8 > b[1]:2;pass,第二次内部循环;j=1;假如b[0]:8 > b[2]:1;pass,第三次内部循环;j=2;假如b[0]:8 > b[3]:55;不成立,执行index = 3;第四次内部循环;j=3;假如b[3]:55 > b[4];pass;交换b[4] 和 b[3],通过第一次外部循环,拿到最大的值,放在最后,num=3;结束第一次外部循环。以此类推,获得最终结果。选择排序每次内部循环交换一次列表的值,比冒泡排序对列表的操做更少。编程
原理: 将n个元素的数列分为已有序和无序两个部分,如 插入排序过程示例 插入排序过程示例 下所示: {{a1},{a2,a3,a4,…,an}} {{a1⑴,a2⑴},{a3⑴,a4⑴ …,an⑴}} … {{a1(n-1),a2(n-1) ,…},{an(n-1)}} 每次处理就是将无序数列的第一个元素与有序数列的元素从后往前逐个进行比较,找出插入位置,将该元素插入到有序数列的合适位置中。 假设在一个无序的数组中,要将该数组中的数按插入排序的方法从小到大排序。假设啊a[]={3,5,2,1,4};插入排序的思想就是比大小,知足条件交换位置,一开始会像冒泡排序同样,但会比冒泡多一步就是交换后(a[i]=a[i+1]后)原位置(a[i])会继续和前面的数比较知足条件交换,直到a[i+1]前面的数组是有序的。好比在第二次比较后数组变成a[]={2,3,5,1,4};
插入排序初级代码以下:数组
c=[6,4,3,22,12,8,9] for i in range(len(c)-1): flag = c[i+1] while i >= 0 and c[i] > flag: middle = c[i] c[i] = c[i+1] c[i+1] = middle i -= 1 print(c)
执行结果以下:安全
[3, 4, 6, 8, 9, 12, 22]
代码剖析:执行开始:此时维护的有序列表为[6],第一次外部循环;i=0;flag=c[1]=4;第一次内部循环;i=0 && c[0]:6 > 4,把c[1]放到c[0]后,结果如同交换c[0]和c[1],此时维护的有序列表为[4,6],i=-1,退出内部循环。第二次外部循环;i=1;flag=c[2]=3;第一次内部循环;i=1 && c[1]:6 > 3,把c[2]放在c[1]前,如同交换,此时c[0]=4;c[1]=3;c[2]=6;而后进行i自减1;i=0;第二次内部循环;i=0 && c[0]:4 > 3,把c[1]放在c[0]前,如同交换,此时c[0]=3;c[1]=4;c[2]=6;退出内部循环。以此类推,拿到最终的列表。bash
liukai@bogon:~/PycharmProjects/s13/day6$ cat fanshe.py #!/usr/bin/env python3 # -*- coding=utf-8 -*- # Author : LiuKai def run(): inp = input("请输入url: ") if inp.find("/") != -1: m,f = inp.split("/") obj = __import__(m) if hasattr(obj,f): func = getattr(obj,f) func() else: print("404") else: print("404") if __name__ == '__main__': run()liukai@bogon:~/PycharmProjects/s13/day6$ cat account.py #!/usr/bin/env python3 # -*- coding=utf-8 -*- # Author : LiuKai def login(): print("登录页面") def logout(): print("登出页面") liukai@bogon:~/PycharmProjects/s13/day6$ cat order.py #!/usr/bin/env python3 # -*- coding=utf-8 -*- # Author : LiuKai def home(): print("主页面")
执行fanshe.py结果以下:框架
请输入url: account/login
登录页面
代码需求分析:
1.实例分析:该代码用反射来实现伪造web框架的路由系统
2.反射须要用到的方法:getattr、delattr、setattr、hasattr
3.导入模块:import xxx、from xxx import ooo、__import__
代码剖析:当输入account/login时,m=account,f=login;__import__(m):__import__,能够把字符串当作参数,导入这个模块。正常import时,必须写模块名,不能以字符串的形式,这时候就须要__import__()了。这里须要说一下,__import__()函数有个参数叫fromlist=True/False,当为True时,能够导入模块的绝对路径,例如:__import__(lib.m,fromlist=True),这能够导入lib文件夹下的m模块,假如不写fromlist=True,只能导入lib模块,就遗漏了m。回到刚才,到入account模块后,有个hasattr函数,这个函数的用途是,当模块中有这个函数,返回True,不然返回False。接下来,getattr()函数,能够从函数名字符串到函数引用的一个映射,getattr(obj,f)就至关于拿到了account模块里的login()函数,而后执行该函数。
官档有更详细的解释,os就是提供对操做系统进行调用的接口
1 os.getcwd() 获取当前工做目录,即当前python脚本工做的目录路径 2 os.chdir("dirname") 改变当前脚本工做目录;至关于shell下cd 3 os.curdir 返回当前目录: ('.') 4 os.pardir 获取当前目录的父目录字符串名:('..') 5 os.makedirs('dirname1/dirname2') 可生成多层递归目录 6 os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 7 os.mkdir('dirname') 生成单级目录;至关于shell中mkdir dirname 8 os.rmdir('dirname') 删除单级空目录,若目录不为空则没法删除,报错;至关于shell中rmdir dirname 9 os.listdir('dirname') 列出指定目录下的全部文件和子目录,包括隐藏文件,并以列表方式打印 10 os.remove() 删除一个文件 11 os.rename("oldname","newname") 重命名文件/目录 12 os.stat('path/filename') 获取文件/目录信息 13 os.sep 输出操做系统特定的路径分隔符,win下为"\\",Linux下为"/" 14 os.linesep 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n" 15 os.pathsep 输出用于分割文件路径的字符串 16 os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix' 17 os.system("bash command") 运行shell命令,直接显示 18 os.environ 获取系统环境变量 19 os.path.abspath(path) 返回path规范化的绝对路径 ###经常使用 20 os.path.split(path) 将path分割成目录和文件名二元组返回 21 os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 ##经常使用 22 os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素 23 os.path.exists(path) 若是path存在,返回True;若是path不存在,返回False 24 os.path.isabs(path) 若是path是绝对路径,返回True 25 os.path.isfile(path) 若是path是一个存在的文件,返回True。不然返回False 26 os.path.isdir(path) 若是path是一个存在的目录,则返回True。不然返回False 27 os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径以前的参数将被忽略 ##经常使用 28 os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间 29 os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间
hashlib模块主要用于加密相关的操做。
import hashlib obj = hashlib.md5(bytes("lk",encoding='utf8')) obj.update(bytes("123",encoding="UTF-8")) result = obj.hexdigest() print(result)
执行结果以下:
a0a58adb9fd5bb904f771e6e7d619ffb
代码剖析:上面代码中要给字符串'123'进行加密,bytes("lk",encoding="uft8")的意思是在123的基础上再次按照字符串"lk"加密。这样作会更加安全。hexdigest()函数输出加密后的值。
1 sys.argv 命令行参数List,第一个元素是程序自己路径 2 sys.exit(n) 退出程序,正常退出时exit(0) 3 sys.version 获取Python解释程序的版本信息 4 sys.maxint 最大的Int值 5 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 6 sys.platform 返回操做系统平台名称
利用sys模块模拟进度条:
import sys import time def view_bar(num, total): rate = float(num) / float(total) rate_num = int(rate * 100) # r = '\r%s%d%%' % ("=" * num,rate_num, ) r = '\r[{:100s}]{:d}%'.format("+" * num,rate_num) sys.stdout.write(r) sys.stdout.flush() if __name__ == '__main__': for i in range(0, 101): time.sleep(0.05) view_bar(i, 100)
执行结果以下:
[++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++]100%
代码剖析:\r表明return,光标回到当前行首,能实现进度条的效果。sys.stdout.write()屏幕输出,sys.stdout.flush()方法的功能是:强制把缓冲器的内容刷到终端。
正则表达式并非Python的一部分。正则表达式是用于处理字符串的强大工具,拥有本身独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十分强大。得益于这一点,在提供了正则表达式的语言里,正则表达式的语法都是同样的,区别只在于不一样的编程语言实现支持的语法数量不一样;但不用担忧,不被支持的语法一般是不经常使用的部分。若是已经在其余语言里使用过正则表达式,只须要简单看一看就能够上手了。
下图展现了使用正则表达式进行匹配的流程:
正则表达式的大体匹配过程是:依次拿出表达式和文本中的字符比较,若是每个字符都能匹配,则匹配成功;一旦有匹配不成功的字符则匹配失败。若是表达式中有量词或边界,这个过程会稍微有一些不一样,但也是很好理解的,看下图中的示例以及本身多使用几回就能明白。
下图列出了Python支持的正则表达式元字符和语法:
简单正则举例:
import re str1 = "lk lk666 *_lk lk /lklk01" result1 = re.findall(r".",str1) print("result1:",result1) result2 = re.findall(r".*",str1) print("result2:",result2) result3 = re.findall(r".+",str1) print("result3:",result3) result4 = re.findall(r".?",str1) print("result4:",result4) result5 = re.findall(r"\d",str1) print("result5:",result5) result6 = re.findall(r"\w",str1) print("result6:",result6) result7 = re.findall(r"\s",str1) print("result7:",result7) result8 = re.findall(r"\D",str1) print("result8:",result8) result9 = re.findall(r"\W",str1) print("result9:",result9) result10 = re.findall(r"\S",str1) print("result10:",result10) result11 = re.findall(r"^lk",str1) print("result11:",result11) result12 = re.findall(r"01$",str1) print("result12:",result12) result13 = re.findall(r"\d{2}",str1) print("result13:",result13) result14 = re.findall(r"\blk\b",str1) print("result14:",result14) result15 = re.findall(r"[lL]k",str1) print("result15:",result15) result16 = re.findall(r"\b[^\d]k\b",str1) print("result16:",result16)
执行结构以下:
result1: ['l', 'k', ' ', 'l', 'k', '6', '6', '6', ' ', '*', '_', 'l', 'k', ' ', 'l', 'k', ' ', '/', 'l', 'k', 'l', 'k', '0', '1'] result2: ['lk lk666 *_lk lk /lklk01', ''] result3: ['lk lk666 *_lk lk /lklk01'] result4: ['l', 'k', ' ', 'l', 'k', '6', '6', '6', ' ', '*', '_', 'l', 'k', ' ', 'l', 'k', ' ', '/', 'l', 'k', 'l', 'k', '0', '1', ''] result5: ['6', '6', '6', '0', '1'] result6: ['l', 'k', 'l', 'k', '6', '6', '6', '_', 'l', 'k', 'l', 'k', 'l', 'k', 'l', 'k', '0', '1'] result7: [' ', ' ', ' ', ' '] result8: ['l', 'k', ' ', 'l', 'k', ' ', '*', '_', 'l', 'k', ' ', 'l', 'k', ' ', '/', 'l', 'k', 'l', 'k'] result9: [' ', ' ', '*', ' ', ' ', '/'] result10: ['l', 'k', 'l', 'k', '6', '6', '6', '*', '_', 'l', 'k', 'l', 'k', '/', 'l', 'k', 'l', 'k', '0', '1'] result11: ['lk'] result12: ['01'] result13: ['66', '01'] result14: ['lk', 'lk'] result15: ['lk', 'lk', 'lk', 'lk', 'lk', 'lk'] result16: ['lk', 'lk']
代码剖析:就不解释了,直接看上图吧。。。
正则表达式一般用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也多是默认非贪婪),老是尝试匹配尽量多的字符;非贪婪的则相反,老是尝试匹配尽量少的字符。例如:正则表达式"ab*"若是用于查找"abbbc",将找到"abbb"。而若是使用非贪婪的数量词"ab*?",将找到"a"。
与大多数编程语言相同,正则表达式里使用"\"做为转义字符,这就可能形成反斜杠困扰。假如你须要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将须要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可使用r"\\"表示。一样,匹配一个数字的"\\d"能够写成r"\d"。有了原生字符串,你不再用担忧是否是漏写了反斜杠,写出来的表达式也更直观。
re.compile(strPattern[, flag]):
compile()方法是Pattern类的工厂方法,用于将字符串形式的正则表达式编译为Pattern对象,
第二个参数flag是匹配模式,取值可使用按位或运算符'|'表示同时生效,好比re.I | re.M。另外,你也能够在regex字符串中指定模式,好比re.compile('pattern', re.I | re.M)与re.compile('(?im)pattern')是等价的。
可选值有:
import re str2 = "lk1kaks618fuck" c = re.compile("[a-z]{1,4}") result = re.match(c,str2) print(result.group())
执行结果以下:
lk
代码剖析:c为定义了一个Pattern对象,就是那个正则规则。好处是能够供屡次使用,相似变量的功效。
match(string[, pos[, endpos]]) | re.match(pattern, string[, flags]):
这个方法将从string的pos下标处起尝试匹配pattern;若是pattern结束时仍可匹配,则返回一个Match对象;若是匹配过程当中pattern没法匹配,或者匹配未结束就已到达endpos,则返回None。
pos和endpos的默认值分别为0和len(string);re.match()没法指定这两个参数,参数flags用于编译pattern时指定匹配模式。
注意:这个方法并非彻底匹配。当pattern结束时若string还有剩余字符,仍然视为成功。想要彻底匹配,能够在表达式末尾加上边界匹配符'$'。
import re
str2 = "lk1kaks618fuck"
c = re.compile("[a-z]{1,2}")
result = re.match(c,str2)
print(result.group())
print(result.groups())
print(result.string)
print(result.re)
print(result.pos)
print(result.endpos)
print(result.lastindex)
print(result.start())
print(result.group())
print(result.groupdict())
print(result.end())
print(result.span()[1])
执行结果以下:
lk
()
lk1kaks618fuck
re.compile('[a-z]{1,2}')
0
14
None
0
lk
{}
2
2
代码剖析:
Match对象是一次匹配的结果,包含了不少关于这次匹配的信息,可使用Match提供的可读属性或方法来获取这些信息。
属性:
方法:
注:match()方法只是匹配字符串开头,假如正则规则匹配的在中间,则没法匹配,须要下面的search()方法。
search(string[, pos[, endpos]]) | re.search(pattern, string[, flags]):
这个方法用于查找字符串中能够匹配成功的子串。从string的pos下标处起尝试匹配pattern,若是pattern结束时仍可匹配,则返回一个Match对象;若没法匹配,则将pos加1后从新尝试匹配;直到pos=endpos时仍没法匹配则返回None。
pos和endpos的默认值分别为0和len(string));re.search()没法指定这两个参数,参数flags用于编译pattern时指定匹配模式。
import re str2 = "lk1kaksklk618fuck" c = re.compile("[a-z]{1,2}") result = re.search(c,str2) print(result.group())
执行结果以下:
lk
代码剖析:search()从开头匹配假如匹配不到也能够继续向后匹配,这是和match()的不一样之处。
split(string[, maxsplit]) | re.split(pattern, string[, maxsplit]):
按照可以匹配的子串将string分割后返回列表。maxsplit用于指定最大分割次数,不指定将所有分割。
import re str2 = "lk1kaks618fuck55" c = re.compile(r"[a-z]{1,2}") result = re.split(c,str2) print(result)
执行结果以下:
['', '1', '', '618', '', '55']
代码剖析:这个相似于字符串的split()方法,不过比那个更增强大,能够根据正则规则分隔,split的maxsplit参数能够指定分隔多少次。
findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags]):
搜索string,以列表形式返回所有能匹配的子串。
import re str2 = "lk1kaks618fuck55" c = re.compile(r"[a-z]{1,2}") result = re.findall(c,str2) print(result)
执行结果以下:
['lk', 'ka', 'ks', 'fu', 'ck']
代码剖析:这个findall()方法很经常使用,匹配的结果以列表的形式表示,很方便处理。
sub(repl, string[, count]) | re.sub(pattern, repl, string[, count]):
使用repl替换string中每个匹配的子串后返回替换后的字符串。
当repl是一个字符串时,可使用\id或\g<id>、\g<name>引用分组,但不能使用编号0。
当repl是一个方法时,这个方法应当只接受一个参数(Match对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。
count用于指定最多替换次数,不指定时所有替换。
import re
str2 = "lk1kaks618fuck55"
c = re.compile(r"[a-z]{1,2}")
result = re.sub(c,"xx",str2,count=2)
print(result)
执行结果以下:
xx1xxks618fuck55
代码剖析:count能够指定替换的次数,默认是所有。还有个subn()函数,用法同样,不过能够返回一个元组,第一个元素为替换后的字符串,第二个元素是替换的次数。
import re str3 = "aaa bbb ccc aaa ccc ddd" r = re.split("ccc", str3, 1) print(r) #====================== str4 = "aaa ddd acc ddd acc ddd aaa" r1 = re.split("(acc)", str4) print(r1) r2 = re.split("(a(cc))", str4) print(r2)
执行结果以下:
['aaa bbb ', ' aaa ccc ddd'] ['aaa ddd ', 'acc', ' ddd ', 'acc', ' ddd aaa'] ['aaa ddd ', 'acc', 'cc', ' ddd ', 'acc', 'cc', ' ddd aaa']
代码剖析:split()的无分组状况就是正常分隔,当有分组时,也会打印相应分组的字符串,当有两个以上括号时,都会打印出来。
findall()、match()、search()的分组方法如例子:
import re str3 = "aaa bbb ccc aaa ccc ddd" r = re.findall("\w{3} c", str3) print(r) # 有分组 str4 = "aaa ddd acc ddd acc ddd aaa" r1 = re.findall("(\w{3}) a", str4) print(r1) r2 = re.match("(^aaa) d",str4) r3 = re.search("(\w{2})\w",str4) print(r2.groups()[0]) print(r3.groups()[0])
执行结果以下:
['bbb c', 'aaa c'] ['ddd', 'ddd', 'ddd'] aaa aa