迭代器
迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个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')
#如果 函数本身 有返回值 之前的方式 则无法得到返回值