目录
- 正则表达式
- 三目运算
- 列表生成式
- 生成器:generator
- 斐波拉契数列生成
- 正则深入
- 冒泡排序
- 时间复杂度
- 模块介绍
正则表达式
栗子:
import re #导入类库
m1=re.match("abc","abcdef") #如果有匹配“abc”的则返回
m2=re.match("[0-9]","6abc") #如果第一个字符匹配数字,则返回
m3=re.match("[0-9]{1,10}","7677abc77") #如果前面的数匹配数字,匹配次数1到10次,则返回
m4=re.findall("[a-zA-Z]","7677abc") #将匹配的字母 按单个生成列表
m5=re.findall(".+","7546abc89") #匹配任意字符,任意次数,返回列表
m6=re.search("\d+","7546abc89") #找出匹配数字,只会匹配第一次,就返回
m7=re.sub("\d+","*","7546abc89") #将所有数字组替换成星号
if m1:
print ("m1:",m1)
print("m1.group():",m1.group())
print("---------")
print("m2.group():",m2.group())
print("---------")
print("m3.group():",m3.group())
print("---------")
print ("m4:",m4)
print("---------")
print("m5:",m5)
print("---------")
print("m6.group():",m6.group())
print("---------")
print("m7:",m7)
#结果为:
m1: <_sre.SRE_Match object; span=(0, 3), match='abc'>
m1.group(): abc
---------
m2.group(): 6
---------
m3.group(): 7677
---------
m4: ['a', 'b', 'c']
---------
m5: ['7546abc89']
---------
m6.group(): 7546
---------
m7: *abc*
#ps 有的返回的是group字符串 ,有的是返回列表
- .* #匹配0到多个
- .+ #匹配1到多个
- \w #匹配所有字母数字
- \W #匹配所有非字母数字
- \s #匹配空白字符
- \S #匹配非空字符
- \d #匹配所有数字
- \D #匹配任意非数字
- ^ # ^\d 以数字开头 , [^\d] 非数字
- $ #以。。。结尾
三目运算
ret= 3 if 3 < 5 else 5 #如果条件成立 则将3赋值给ret ,否则将5赋值给ret
print(ret)
#结果为:
3
列表生成式,迭代器&生成器
列表生成式
要求将列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 每个值加一
方法一:
a=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b=[]
for i in a :
b.append(i+1)
a=b
print("新的a:",a)
#结果为:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
方法二:
a=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for index,i in enumerate(a):
a[i]+=1
print("新的a:",a)
#直接修改原表
方法3:
a=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a=map(lambda x:x+1 ,a)
print("新的a:",a)
print("新的a:",type(a))
for i in a :
print (i)
#结果为:
新的a: <map object at 0x0000027D8B8FEF28>
新的a: <class 'map'>
1
2
……
#这样a被转化成了 map, 遍历才能打印出,可以强制转化为列表
方法4:
a=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a=[i+1 for i in range(10)]
print("新的a:",a)
迭代器
我们已经知道,可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list、tuple、dict、set、str等;
一类是generator,包括生成器和带yield的generator function。
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable
迭代器是访问集合元素的一种方式,迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问,不能后退,只能前进,迭代器在迭代到某元素时才计算该元素,而在这之前,元素可以不存在,这个特点可以遍历巨大的集合。
a=iter([1,2,3,4,5])
print(a.__next__())
print(a.__next__())
......
#结果为:
1
2
......
生成器:generator
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:
g=(x*x for x in range(1,5))
for i in g:
print (i)
#结果为:
1
4
9
16
#ps: 可以用 next(g) 一个一个的取
斐波拉契数列生成
方法一: 采用while循环
fib_list=[] #定义一个空列表,用来接收斐波拉契数列
def fib(max): #定义一个最大循环次数
n,a,b=0,0,1 #将n,a,b 分别赋值
while n<max: #当n小于最大值时
#print(b)
a,b=b,a+b #将b的值赋给a, a+b的值赋给b
fib_list.append(b) #将b的值添加入列表
n+=1
print("fib_list:",fib_list)
return "done"
fib(10) #执行该函数
#结果为:
fib_list: [1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
方法二:
#采用递归
fib_list=[] #定义一个空列表用来接收得到的值
def fib(a,b,max):
c=a+b #定义c
max-=1 #每循环一次max减一
#print (c)
fib_list.append(c)
if max!=0: #如果max不等于0,继续递归
fib(b,c,max)
fib(0,1,10)
print(fib_list)
#结果为:
[1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
如果函数中包含yield语法,则这个函数叫生成器
yield 一般与 send结合, yield负责接收数据
仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。
也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:
def fib(max):
n,a,b=0,0,1
while n< max:
a,b=b,a+b
yield b #在循环过程中不断调用yield,就会不断中断
n+=1
return "done"
data=fib(10)
print(data.__next__())
print(data.__next__())
print(data.__next__())
print("干点别的事")
print(data.__next__())
#或者直接用for循环遍历
print("......\n----------")
for i in fib(3):
print(i)
#结果为:
1
2
3
干点别的事
5
......
----------
1
2
3
在上面fib的例子,我们在循环过程中不断调用yield,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。
同样的,把函数改成generator后,我们基本上从来不会用next()来获取下一个返回值,而是直接使用for循环来迭代。
正则深入
import re
str="123abc456"
p=re.compile("^[0-9]+") #以数字开头
m=p.match(str)
print("m.group():",m.group())
#等价于
m2=re.match("^[0-9]+",str)
print("m2.group():",m2.group())
#结果为:
m.group(): 123
m2.group(): 123
#ps: 先定义一个匹配条件,可以实现复用
#匹配出ip地址
import re
str="192.168.1.233"
m=re.match("([0-9]+\.){1,3}\d{1,3}",str)
print(m.group())
#结果为:
192.168.1.233
re.split(“[0-9]”,str) #以数字为分割符生成列表
re.sub(“[0-9]”,”*”,str) #将所有数字替换成星号
re.search(“^a.*i$”,str) #匹配以a开头,i结尾的集合
re.search(“(1)(358)\d{9}”,str) #匹配手机号
re.match(r”[0-9.a-z]{1,26}@[0-9.a-z]{1,20}.[0-9a-z]{1,8}”,str) #以r开头为不转义, 邮箱匹配
分组匹配:
import re
addr="school,Beijin Changpin :010-886668"
m=re.search(r'(\w+),(.+):(\S+)',addr) #分组匹配
print(m.group())
print(m.group(1))
print(m.group(2))
print(m.group(3))
#结果为:
school,Beijin Changpin :010-886668
school
Beijin Changpin
010-886668
冒泡排序
data=[10,4,22,11,33,4,1,99]
怎么让data按从小到大排列
#怎么让data按从小到大排列
data=[10,4,22,11,1]
for j in range(1,len(data)): #每次把最大的数放到最后,可以大量减少遍历次数
for i in range(len(data)-j): #因为遍历data的话,同时操作数据会引起混乱
if data[i]>data[i+1]:
data[i],data[i+1]=data[i+1],data[i] #交换数据
print (data)
#结果为:
[1, 4, 10, 11, 22]
时间复杂度
时间频度
时间与执行的次数成正比。 时间频度记为T(n), T为执行次数,n为问题规模
时间复杂度
O(f(n)) 为时间复杂度, T(n) 可以能等于O(f(n)), f(n) 为辅助函数
指数时间
计算时间m(n) ,n呈线性增长, 所花的时间以指数增长
像 两次for循环 ,即为 n^2
T(n)=O(n^2)
若T(n)的上界与输入的大小无关,则称其具有常数时间O(1)
若遍历一次为O(n), n为常量, 也可以称之为具有常数时间
对数时间
T(n)=O(log n)
称其具有对数时间,常见的有二分搜索(递归算法),二叉树。
线性时间
T(n)=O(n)
运行的时间与输入成线性关系,正比
ps:O(n^m)>O(n)>O(log n) 即具有对数时间的算法效率最高
模块介绍
模块分为 :自定义模块,内置模块,开源模块
自定义一个网站模块,dj 模块:
以上为基本的建站流程
数据序列化
python 自己的序列化函数 需要存储为二进制
import pickle #导入python的序列化类库
#创建一个文件,保存时用二进制编码
f=open("user_acc.txt","wb")
info={
"aa":"123",
"bb":"456",
}
#将账户信息序列化,然后存储
f.write((pickle.dumps(info)))
f.close()
#结果为:
user_acc.txt内容: �}q (X aaqX 123qX bbqX 456qu.
#ps 为编译后的数据
f=open("user_acc.txt","rb")
#将数据读入内存,然后反序列化
data=pickle.loads(f.read())
print(data)
#结果为:
{'aa': '123', 'bb': '456'}
用json序列化, json支持所有的语言, 但是只能用于 列表,元祖,字典的序列化
import json #导入json序列化类库
#创建一个文件,按平时保存即可
f=open("user_acc.txt","w")
info={
"aa":"123",
"bb":"456",
}
#将账户信息序列化,然后存储
f.write((json.dumps(info)))
f.close()
#结果为:
user_acc.txt内容:{"aa": "123", "bb": "456"}
f=open("user_acc.txt","r")
#将数据读入内存,然后反序列化
data=json.loads(f.read())
print(data)
#结果为:
{'aa': '123', 'bb': '456'}
所以python的序列化pickle,比json 更强大。 pickle 可以序列化一切对象
在及时数据的存档应用比较广泛。比如游戏存档