迭代器:
迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完才结束。迭代器只能向前不会后退,不过这没什么大不了的,因为人们很少在迭代中往后退。另外,迭代器的一大优点是不要求事先准备好整个迭代过程中的所有元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件。
特点:
1、 访问者不需要关心迭代器内部的结构,仅需要通过next()方法不断去取下一个内容。
2、 不能随机访问集合中的某个值,只能从头到尾依次访问。
3、 访问到一半时不能往回退。
4、 便于循环比较大的数据集合,节省内存。
1 names=iter(['alex','jack','rain'])2 print(names)3 print(names.__next__())4 print(names.__next__())5 67 alex8 jack
生成器的使用:
定义:一个函数调用的时候返回一个迭代器,那这个函数就叫做生成器,如果函数中包含yield语法,那这个函数就会变成生成器。
1 def cash_out(amount): 2 while amount>0: 3 amount-=100 4 yield 100 5 print('又来取钱呢啦!') 6 atm=cash_out(500) 7 print(type(atm)) 8 print(atm.__next__()) 9 print(atm.__next__())10 print('叫个大保健…')11 print(atm.__next__())12 13 又来取钱呢啦!1415 10016 10017 叫个大保健…18 100
作用:
这个yield的主要效果呢,就是可以使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间还可以再重新调用这个函数,从上次yield的下一句开始执行。
另外,还可通过yield实现在单线程的情况下实现并发运算的效果(这就是我们所熟知的生产者-消费者模型)
生产者-消费者模型:
1 import time 2 def consumer(name): 3 print("%s 准备吃包子啦!" %name) 4 while True: 5 baozi = yield 6 7 print("包子[%s]来了,被[%s]吃了!" %(baozi,name)) 8 9 def producer(name):10 c = consumer('A')11 c2 = consumer('B')12 c.__next__()13 c2.__next__()14 print("老子开始准备做包子啦!")15 for i in range(10):16 time.sleep(1)17 print("做了2个包子!")18 c.send(i)19 c2.send(i)20 21 producer("alex")
装饰器原理介绍和基本实现:
原理:
1 def login(func): 2 print('passed user verification…') 3 return func 4 def home(name): 5 print('welcome [%s] to home page'%name) 6 def tv(name): 7 print('welcome [%s] to tv page'%name) 8 def moive(name): 9 print('welcome [%s] to moive page'%name)10 tv=login(tv)11 tv(name='peony')12 13 passed user verification…14 welcome [peony] to tv page
基本实现:
1 def login(func): 2 def inner(arg): 3 print('passed user verification…') 4 func(arg) 5 return inner 6 def home(name): 7 print('welcome [%s] to home page'%name) 8 @login 9 def tv(name):10 print('welcome [%s] to tv page'%name)11 def moive(name):12 print('welcome [%s] to moive page'%name)13 tv('Alex')14 15 passed user verification…16 welcome [Alex] to tv page
实现带参数的复杂装饰器:
1 def w1(func): 2 def inner(arg): 3 # 验证1 4 # 验证2 5 # 验证3 6 return func(arg) 7 return inner 8 9 @w110 def f1(arg):11 print 'f1'12 13 一个参数
1 def w1(func): 2 def inner(arg1,arg2): 3 # 验证1 4 # 验证2 5 # 验证3 6 return func(arg1,arg2) 7 return inner 8 9 @w110 def f1(arg1,arg2):11 print 'f1'12 13 两个参数
1 def w1(func): 2 def inner(arg1,arg2,arg3): 3 # 验证1 4 # 验证2 5 # 验证3 6 return func(arg1,arg2,arg3) 7 return inner 8 9 @w110 def f1(arg1,arg2,arg3):11 print 'f1'12 13 三个参数
可以装饰具有处理n个参数的函数的装饰器:
1 def w1(func): 2 def inner(*args,**kwargs): 3 # 验证1 4 # 验证2 5 # 验证3 6 return func(*args,**kwargs) 7 return inner 8 9 @w110 def f1(arg1,arg2,arg3):11 print 'f1'
一个函数可以被多个装饰器装饰:
1 def w1(func): 2 def inner(*args,**kwargs): 3 # 验证1 4 # 验证2 5 # 验证3 6 return func(*args,**kwargs) 7 return inner 8 9 def w2(func):10 def inner(*args,**kwargs):11 # 验证112 # 验证213 # 验证314 return func(*args,**kwargs)15 return inner16 17 18 @w119 @w220 def f1(arg1,arg2,arg3):21 print 'f1'
(1)简单的装饰器:
1 def w1(main_func):2 def outer(request,kargs):3 print('before')4 main_func(request,kargs)5 print('after')6 return outer7 @w18 def show():9 print('show')
其执行流程为:
python解释器就会从上到下解释代码,步骤如下:
- def w1(main_func): ==>将w1函数加载到内存
- @w1
没错,从表面上看解释器仅仅会解释这两句代码,因为函数在没有被调用之前其内部代码不会被执行。从表面上看解释器着实会执行这两句,但是 @w1 这一句代码里却有大文章,@函数名 是python的一种语法糖。如上例@w1内部会执行以下操作:
-
- 执行w1函数,并将 @w1 下面的 函数 作为w1函数的参数,即:@w1 等价于 w1(show),show函数重新定义为w1(show)的返回值
- 执行show(),这个时候是新show()=outer,即为
print('before')main_func(request,kargs)#原来的show()print('after')
(2)复杂的装饰器:
1 def Before(request,kargs): 2 print('before') 3 def After(request,kargs): 4 print('after') 5 def Filter(before_func,after_func): 6 def outer(main_func): 7 def wrapper(request,kargs): 8 before_func(request,kargs) 9 main_func(request,kargs)10 after_func(request,kargs)11 return wrapper12 return outer13 14 @Filter(Before, After)15 def Index(request,kargs):16 print ('index')
其执行流程为:
(1)执行Filter(before,after)
(2)@Filter(before,after)变成@outer,其参数是Index
(3)新Index=wrapper()
递归原理及实现:
递归
特点
要求
1 def calc(n): 2 print(n) 3 if n/2>1: 4 res=calc(n/2) 5 print('res:',res) 6 print("N:",n) 7 return n 8 calc(10) 9 10 1011 5.012 2.513 1.2514 res: None15 N: 2.516 res: 2.517 N: 5.018 res: 5.019 N: 10
(1)使用递归实现二分查找算法,
1 def binary_search(data_source,find_n): 2 mid=int(len(data_source)/2) 3 if len(data_source)>=1: 4 if data_source[mid]>find_n: 5 print("data in left of [%s]"%data_source[mid]) 6 binary_search(data_source[:mid],find_n) 7 elif data_source[mid]
(2)使用递归实现斐波那契数列,
1 def func(arg1,arg2,stop):2 if arg1==0:3 print (arg1,arg2)4 arg3=arg1+arg25 print(arg3)6 if arg3
(3)算法基础之2维数组90度旋转:
data=[[col for col in range(4)] for row in range(4)]for row in data: print(row)print('-------------')for r_index,row in enumerate(data): for c_index in range(r_index,len(row)): tmp=data[c_index][r_index] data[c_index][r_index]=row[c_index] data[r_index][c_index]=tmp print('-------------') for r in data:print(r)
正则表达式基础:
语法:
1 import re #导入模块名2 3 p = re.compile("^[0-9]") #生成要匹配的正则对象 , ^代表从开头匹配,[0-9]代表匹配0至9的任意一个数字, 所以这里的意思是对传进来的字符串进行匹配,如果这个字符串的开头第一个字符是数字,就代表匹配上了4 5 m = p.match('14534Abc') #按上面生成的正则对象 去匹配 字符串, 如果能匹配成功,这个m就会有值, 否则m为Noneif m: #不为空代表匹配上了6 print(m.group()) #m.group()返回匹配上的结果,此处为1,因为匹配上的是1这个字符else: print("doesn't match.")
上面的第2 和第3行也可以合并成一行来写:
m = p.match("^[0-9]",'14534Abc')
它们的效果是一样的,区别在于:第一种方式是提前对要匹配的格式进行了编译(对匹配公式进行解析),这样再去匹配的时候就不用在编译匹配的格式,第2种简写是每次匹配的时候 都 要进行一次匹配公式的编译,所以,如果你需要从一个5w行的文件中匹配出所有以数字开头的行,建议先把正则公式进行编译再匹配,这样速度会快点。
匹配格式
模式 | 描述 |
---|---|
^ | 匹配字符串的开头 |
$ | 匹配字符串的末尾。 |
. | 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。 |
[...] | 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k' |
[^...] | 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。 |
re* | 匹配0个或多个的表达式。 |
re+ | 匹配1个或多个的表达式。 |
re? | 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式 |
re{ n} | |
re{ n,} | 精确匹配n个前面表达式。 |
re{ n, m} | 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式 |
a| b | 匹配a或b |
(re) | G匹配括号内的表达式,也表示一个组 |
(?imx) | 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。 |
(?-imx) | 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。 |
(?: re) | 类似 (...), 但是不表示一个组 |
(?imx: re) | 在括号中使用i, m, 或 x 可选标志 |
(?-imx: re) | 在括号中不使用i, m, 或 x 可选标志 |
(?#...) | 注释. |
(?= re) | 前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。 |
(?! re) | 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功 |
(?> re) | 匹配的独立模式,省去回溯。 |
\w | 匹配字母数字 |
\W | 匹配非字母数字 |
\s | 匹配任意空白字符,等价于 [\t\n\r\f]. |
\S | 匹配任意非空字符 |
\d | 匹配任意数字,等价于 [0-9]. |
\D | 匹配任意非数字 |
\A | 匹配字符串开始 |
\Z | 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。c |
\z | 匹配字符串结束 |
\G | 匹配最后匹配完成的位置。 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 |
\B | 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 |
\n, \t, 等. | 匹配一个换行符。匹配一个制表符。等 |
\1...\9 | 匹配第n个分组的子表达式。 |
\10 | 匹配第n个分组的子表达式,如果它经匹配。否则指的是八进制字符码的表达式。 |
正则表达式常用5种操作:
re.match(pattern, string) # 从头匹配
re.search(pattern, string) # 匹配整个字符串,直到找到一个匹配
re.split() # 将匹配到的格式当做分割点对字符串分割成列表
1 import re2 m = re.split("[0-9]", "alex1rain2jack3helen rachel8")3 print(m)4 输出:5 ['alex', 'rain', 'jack', 'helen rachel', '']
re.findall() # 找到所有要匹配的字符并返回列表格式
1 import re2 m = re.findall("[0-9]", "alex1rain2jack3helen rachel8")3 print(m)4 输出:5 ['1', '2', '3', '8']
re.sub(pattern, repl, string, count,flag) # 替换匹配到的字符
1 import re2 m=re.sub("[0-9]","|", "alex1rain2jack3helen rachel8",count=2 )3 print(m)4 输出:5 alex|rain|jack3helen rachel8
正则表达式实例
字符匹配
实例 | 描述 |
---|---|
python | 匹配 "python". |
字符类
实例 | 描述 |
---|---|
[Pp]ython | 匹配 "Python" 或 "python" |
rub[ye] | 匹配 "ruby" 或 "rube" |
[aeiou] | 匹配中括号内的任意一个字母 |
[0-9] | 匹配任何数字。类似于 [0123456789] |
[a-z] | 匹配任何小写字母 |
[A-Z] | 匹配任何大写字母 |
[a-zA-Z0-9] | 匹配任何字母及数字 |
[^aeiou] | 除了aeiou字母以外的所有字符 |
[^0-9] | 匹配除了数字外的字符 |
特殊字符类
实例 | 描述 |
---|---|
. | 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。 |
\d | 匹配一个数字字符。等价于 [0-9]。 |
\D | 匹配一个非数字字符。等价于 [^0-9]。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\w | 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。 |
\W | 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。 |
re.match与re.search的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。