迭代器
迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件
特点:
- 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
- 不能随机访问集合中的某个值 ,只能从头到尾依次访问
- 访问到一半时不能往回退
- 便于循环比较大的数据集合,节省内存
from collections import Iterator
# isinstance() 判断是否是 迭代器# 可以被next()函数不断返还下一个值的被称为迭代器# iter() 可以将 list dict str 编程迭代器
生成器generator
定义:一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器
#!/usr/bin/env python # -*- coding: utf-8 -*- # By Garrett a = [i*2 for i in range(10)] print(a) # 生成器 # g = (i*2 for i in range(10)) # # print(g) # # for i in g: # print(i) # # 生成器只记住当前位置 只有一个 __next__() 方法 ''' def fib(max): n,a,b = 0,0,1 while n<max: print(b) a,b = b,a+b n = n+1 return 'ok' fib(10) ''' # 将这个函数改成生成器 将 print 改成 yield 即可 def fib(max): n,a,b = 0,0,1 while n<max: yield b a,b = b,a+b n = n+1 return 'ok' f = fib(10) print(f.__next__()) # 如果你取得次数超过这个函数生成的个数,那么return 的结果 会作为异常抛出
这个yield的主要效果呢,就是可以使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间还可以再重新调用这个函数,从上次yield的下一句开始执行。
另外,还可通过yield实现在单线程的情况下实现并发运算的效果
# 生成器可以用来实现 单线程下的并行效果 # 生成器可以用来实现 单线程下的并行效果 import time def consumer(name): print('%s 要来吃包子了' %name) while True: baozi = yield print('包子 %s 来了,被 %s 吃了 ' %(baozi,name)) ''' c = consumer('A') 是一个生产器 但是yield 没有值 c.__next__() 会让生成器执行到yield 并暂停 c.send(i) 会让生成器继续执行到下一次yield 处 并给yield赋值 ''' def producer(name): c = consumer('A') c2 = consumer('B') c.__next__() c2.__next__() for i in range(10): time.sleep(1) print('生产了1波包子') c.send(i) c2.send(i) producer('jack')
装饰器
直接 看银角大王写的文档 http://www.cnblogs.com/wupeiqi/articles/4980620.html
# 装饰器:本质是函数,用来装饰其他函数,就是为其他函数添加附加功能 # # 原则 1 不能修改被装饰函数的源代码 2 不能修改被装饰函数的调用方式 #函数就是变量 高阶函数+嵌套函数 = 装饰器 import time def timmer(func): def warpper(*args,**kwargs): start_time = time.time() func() stop_time = time.time() print('the func run time is {}'.format(stop_time-start_time)) return warpper @timmer def test1(): time.sleep(3) print('in the test1') return 0 test1()
import time #1 高阶函数 把函数当做变量传入 #2 返回值是函数名 def bar(): time.sleep(2) print('i am bar') # def timmer(func): # start = time.time() # func() # stop = time.time() # print('func run time is %s' %(stop-start)) # # timmer(bar) #上面解决了装饰器的第一个需求 没有改变源函数的代码 但是改变了调用方式 ''' def wapper(func): start = time.time() func() stop = time.time() print('func run time is %s' %(stop-start)) return func ''' #print(wapper(bar)) # return函数名 得到的是内存地址 韩书即变量 得到内存地址可以直接调用 # bar = wapper(bar) # bar() # 但是会导致 bar函数 运行了两遍 #嵌套函数 在一个函数体内声明一个函数 # def foo(): # def bar(): # print('i am bar') # bar() def timmer(func): def wapper(*args,**kwargs): start = time.time() func(*args,**kwargs) stop = time.time() print('func run time is %s' % (stop - start)) return wapper @timmer #test = timmer(test) def test(): time.sleep(1) print('i am test') #test = timmer(test) test() # 当一个修饰器需要修饰多个函数的时候 如果 有的函数有参数 有的函数没有参数 那么 在修饰器中定义的函数就需要是不定参数的 @timmer def test2(name): time.sleep(1.5) print('name is {}'.format(name)) test2('jack') #如果 函数本身 有返回值 之前的方式 则无法得到返回值