一、迭代器
1.Iterable(可迭代的)
我们已经知道可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型:list tuple dict set str 等
一类是generator 包括生成器和带yield的generator function
这些可以直接作用于for循环的对象统称为可迭代对象 Iterable
可以使用isinstance()判断一个对象是否是Iterable对象
form collections import Iterable
isinstance([ ],Iterable)
true
2.Iterator(迭代器)
而生成器不但可以作用于for循环还可以被next()函数不断调回并返回下一个值 直到最后抛出 stopIteration 错误表示无法继续返回下一个值了
可以被next()函数调用并不断返回的下一个值的对象统称为Iterator迭代器
同样可以使用isinstance()判断一个对象是否是Iterator对象
>>> from collections import Iterator >>> isinstance((x for x in range(10)), Iterator) True >>> isinstance([], Iterator) False >>> isinstance({}, Iterator) False >>> isinstance('abc', Iterator) False
生成器都是Iterator
对象,但list
、dict
、str
虽然是Iterable
,却不是Iterator
。
把list
、dict
、str
等Iterable
变成Iterator
可以使用iter()
函数:
>>> isinstance(iter([]), Iterator) True >>> isinstance(iter('abc'), Iterator) True
Python的for
循环本质上就是通过不断调用next()
函数实现的,例如:
for x in [1, 2, 3, 4, 5]: pass
# 首先获得Iterator对象: it = iter([1, 2, 3, 4, 5]) # 循环: while True: try: # 获得下一个值: x = next(it) except StopIteration: # 遇到StopIteration就退出循环 break
二、生成器
参考:https://blog.csdn.net/weixin_37720172/article/details/78482291
假设某列表元素过于庞大 而且可以通过固定的算法实现 这种一边循环一边计算的机制 被称为 生成器 generator
我们可以用列表生成式来生成一个列表
l=[x for x in range(5)] print (l) [0, 1, 2, 3, 4]
我们可以用类似的方式生成一个生成器
g=(x for x in range(5)) print g <generator object <genexpr> at 0x000000000396D360>
可以看到它返回一个生成器
那么怎么返回这个生成器的值呢? 有两种方法
>>> for m in g:print m ... 0 1 2 3 4 >>> g=(x for x in range(5)) >>> next(g) 0 >>> next(g) 1 >>> next(g) 2 >>> next(g) 3 >>> next(g) 4 >>> next(g) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
生成器在面对庞大的列表时 会大量的节省内存空间 下面这段代码就可以验证一波
import time def get_time(func): def wraper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() print("Spend:", end_time - start_time) return result return wraper @get_time def _list(n): l1 = [list(range(n)) for i in range(n)] del l1 @get_time def _generator(n): ge = (tuple(range(n)) for i in range(n)) del ge _list(1000) _generator(1000)
('Spend:', 0.026999950408935547) ('Spend:', 0.0)
生成器中yield的使用:
yield就是专门给生成器用的return yield的作用在于保存一个generator的状态
还可通过yield实现在单线程情况下实现并发运算的效果
import time def consumer(name): print '%s开始' %name while True: baozi = yield print '%s来了%s吃了' %(baozi,name) def producter(name): c=consumer('A') c1=consumer('B') c.next() c1.next() print 'begin!' for i in range(10): time.sleep(1) c.send(i) c1.send(i) producter('C')
一个函数中含有yield的话 默认调用这个函数的为生成器
yield 可以通过send接收数据
三、装饰器
对已有功能的扩展 不改变源代码
@函数名 称为语法糖 程序执行到语法糖后 会执行此函数 并且以该语法糖下面的函数作为 参数
@函数名 该语法糖中的函数 至少有两层 第一层接收函数 第二层接收 语法糖下面函数所传的参数
注:被装饰的函数所携带的参数
#一个参数 def w1(func): def inner(arg): # 验证1 # 验证2 # 验证3 return func(arg) return inner @w1 def f1(arg): print 'f1' #二个参数 def w1(func): def inner(arg1,arg2): # 验证1 # 验证2 # 验证3 return func(arg1,arg2) return inner @w1 def f1(arg1,arg2): print 'f1' #n个参数 def w1(func): def inner(*args,**kwargs): # 验证1 # 验证2 # 验证3 return func(*args,**kwargs) return inner @w1 def f1(arg1,arg2,arg3): print 'f1' #
一个函数被多个装饰器装饰
def w1(func): def inner(*args,**kwargs): # 验证1 # 验证2 # 验证3 return func(*args,**kwargs) return inner def w2(func): def inner(*args,**kwargs): # 验证1 # 验证2 # 验证3 return func(*args,**kwargs) return inner @w1 @w2 def f1(arg1,arg2,arg3): print 'f1'
四、递归
函数执行过程中调用函数本身
注:递归要有一个明确的出口
递归算法的效率较低 每次递归都要在内存中保存一次函数体
五、简单算法
1、二分查找
def binary_search(data_source,find_s): print data_source mid=len(data_source)/2 if len(data_source) >= 1: if data_source[mid] > find_s: print '%s is in %s left' %(find_s,data_source[mid]) binary_search(data_source[:mid],find_s) elif data_source[mid] < find_s: print '%s is in %s right' % (find_s, data_source[mid]) binary_search(data_source[mid:], find_s) else: print 'find %s' %data_source[mid] else: print 'cant find' if __name__ == '__main__': data=list(range(1,600,3)) binary_search(data,1)
2、二维列表90度旋转
# a=[i for i in range(4)] # print a a=[[i for i in range(4)]for j in range(4)] # print a #for b in a:print b for b_index,b in enumerate(a): #print b,b_index for l in range(b_index,len(b)): tmp=a[b_index][l] a[b_index][l]=a[l][b_index] a[l][b_index]=tmp for c in a :print c print '------'
涉及到列表的下标 可以使用range(len(列表名))
六、python正则
字符:
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束
次数:
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
re.search search,浏览整个字符串去匹配第一个,未匹配成功返回None
re.findall findall,获取非重复的匹配列表;如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果模型中有多个组,则以列表形式返回,且每一个匹配均是元祖;
空的匹配也会包含在结果中
re.match match 从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None
七、python实现简单计算器
#-*- coding:utf-8-*- import re def fg(sz): sz2=[ ] sz3=[ ] for sz_index,i in enumerate(sz1): if i=='(': ks=sz_index+1 elif i==')': js=sz_index for j in range(ks,js): sz2.append(sz1[j]) if j == js-1: cc(sz2) for d in range(ks - 1, js + 1): sz1.pop(ks-1) for x in sz2: sz1.insert(ks-1,x) fg(sz1) cc(sz1) sz3=jj(sz1) return sz3[0] def jj(sz3): for p_index,p in enumerate(sz3): if p == '+': n1=int(sz3[p_index-1]) n2=int(sz3[p_index+1]) n=n1 + n2 #print n n = str(n) sz3.insert(p_index-1,n) sz3.pop(p_index) sz3.pop(p_index) sz3.pop(p_index) #print sz3 jj(sz3) if p == '-': n1=int(sz3[p_index-1]) n2=int(sz3[p_index+1]) n=n1 - n2 n = str(n) sz3.insert(p_index-1,n) sz3.pop(p_index) sz3.pop(p_index) sz3.pop(p_index) jj(sz3) #print sz3 return sz3 def cc(sz2): for l_index,l in enumerate(sz2): if l == '*' : m1=int(sz2[l_index-1]) m2=int(sz2[l_index+1]) m=m1 * m2 m = str(m) sz2.insert(l_index-1, m) sz2.pop(l_index) sz2.pop(l_index) sz2.pop(l_index) cc(sz2) elif l == '/': m1 = int(sz2[l_index - 1]) m2 = int(sz2[l_index + 1]) m = m1 / m2 m=str(m) sz2.insert(l_index - 1, m) sz2.pop(l_index) sz2.pop(l_index) sz2.pop(l_index) cc(sz2) #print sz2 return sz2 if __name__== '__main__': ss=raw_input('请输入:') sz1 = re.findall('[0-9]+|\*|\/|\+|\-|\(|\)',ss) print fg(ss)