1.迭代器
1.1 定义
可以被next()
函数调用并不断返回下一个值的对象称为迭代器:Iterator
。
1.2 可迭代对象 Iterable
以直接作用于for 循环的数据类型有一下几种:
一类:集合数据类型:list,tuple,dict,set,str
一类generator
,包含生成器和带yield
的generator function
这些可以直接用于for循环的对象统称为可迭代对象:Iterable
1.3 iter()
函数
生成器都是 Iterator 对象,但 list 、 dict 、 str 虽然是 Iterable ,却不是 Iterator 。把 list 、 dict 、 str 等 Iterable 变成 Iterator 可以使用 iter() 函数:
from collections import Iterable
a=[1,2,3,4,5,6]
a=iter(a)
print(next(a))
2. 生成器
生成器与列表生成式的本质区别就是:一个已经生成数据了,使用时,如果数据过大,会产生内存溢出,而生成器是只有循环时,才会生成数据。
2.1 generator
创建方法
1.把一个列表生成式的[]
改成()
,就创建了一个generator
g = (x * x for x in range(10))
2.2 使用了yield的函数就是生成器
yield关键字可以看作特殊的return
def fib(times): #打印斐波拉契数列钱times位。
n=0
a,b=0,1
while n
发现如果生成器是函数的话,使用for遍历,无法获取函数的返回值。
方法2:使用next()函数来遍历迭代,可以获取生成器函数的返回值。
f=fib(10)
while True:
try: #因为不停的调用next会报异常,所以要捕捉处理异常
x=next(f) #这里不能直接写next(fib(10)),f否则每次重复调用1
print(x)
except StopIteration as e:
print('生成器返回值:%s'%e.value)
break
3.装饰器
装饰器(Decorators)修改其他函数的功能的函数,有助于让我们的代码更简短。在不改动原代码的情况下,在定义一个函数。
import time
def deco(f):
def wrapper(a,b):
start_time=time.time()
f(a,b)
end_time=time.time()
execution_time=(end_time-start_time)*1000
print("time is %d ms"%execution_time)
return wrapper
@deco
def f(a,b):
print('be on')
time.sleep(1)
print('result is %d'%(a+b))
if __name__=='__main__':
f(3,4)
这里的deco函数就是装饰器,它的参数是一个函数,然后返回值也是一个函数。其中作为参数的这个函数f()就在返回函数wrapper的内部执行。然后在函数f()前面加上@deco,f()函数就相当于被注入了计时功能,现在只要调用f(),它就已经变身为“新的功能更多的函数”
3.2 无固定参数的装饰器
def deco(f):
def wrapper(*args, **kwargs): #
start_time = time.time()
f(*args, **kwargs)
end_time = time.time()
execution_time= (end_time - start_time)*1000
print("time is %d ms" % execution_time)
return wrapper
@deco
def f(a,b):
print("be on")
time.sleep(1)
print("result is %d" %(a+b))
@deco
def f2(a,b,c):
print("be on")
time.sleep(1)
print("result is %d" %(a+b+c))
if __name__ == '__main__':
f2(3,4,5)
f(3,4)
python 中 *args 和kwargs的区别**
1. * args的使用方法:*args将参数打包成tuple给函数调用
def func(x,y,*args):
print(x,y,args)
func(1,2,3,4,5)
def function(**kwargs):
print(kwargs)
function(a=1, b=2, c=3)
3.3 使用多个装饰器,装饰一个函数
import time
def deco01(f):
def wrapper(*args, **kwargs):
print("this is deco01")
start_time = time.time()
f(*args, **kwargs)
end_time = time.time()
execution_time = (end_time - start_time)*1000
print("time is %d ms" % execution_time)
print("deco01 end here")
return wrapper
def deco02(f):
def wrapper(*args, **kwargs):
print("this is deco02")
f(*args, **kwargs)
print("deco02 end here")
return wrapper
@deco01
@deco02
def f(a,b):
print("be on")
time.sleep(1)
print("result is %d" %(a+b))
if __name__ == '__main__':
f(3,4)
4. Filter
、map
、reduce
方法
map()
函数:它接收一个f 和一个list,并通过把函数f一次作用在list的每个元素上,得到一个新的list并返回。
reduce
函数即化简函数;每一次迭代都将上一次的迭代结果与下一个元素一同传入二元func函数中去执行。
reduce(func,seq[,int()])
filter:功能是过滤掉序列中不符合函数条件的元素。
l=[x for x in range(0,10)]
l=list(filter(lambda x : x%2==0,l))
print(l)
5. 函数式编程
变量可以指向函数
f=abs #abs为绝对值函数
print(f(-10))
传入函数:
既然变量可以指向函数,函数的参数能接受变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
def add(a,b,f):
return f(a)+f(b)
4.2 函数作为返回值
高阶函数除了可以作为接收函数作为参数外,还可以吧结果值返回。
可变参求和函数
def cal_sum(*args):
ax=0
for i in args:
ax+=i
return ax
但如果不需要立即求和,而是在后面的代码中,根据需要在计算,可以不返回求和的结果,而是返回求和的函数。
def lazy_sum(*args):
def sum():
ax=0
for i in args:
ax+=i
return ax #return必须要有,才能返回到外部函数
return sum
f=lazy_sum(1,3,5,7,9)
f() #调用f时,才真正计算求和的结果
在上面例子中,在函数lazy_sum中又定义了函数sum,并且内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为"闭包closure"的程序结构拥有极大的威力。
注意:每次调用lazy_sum时,都会返回一个新的函数
闭包
需要注意的问题是,返回的函数并没有立刻执行,而是知道调用了f()才执行
def count():
fs=[]
for i in range(1,4):
def f():
return i*i
fs.append(f)
return fs
f1,f2,f3=count()
f1()
结果全是9,原因在于返回的函数引用了变量i,但它并没有立刻执行,等到3个函数都返回时,他们所应用的变量i已经变成了3,因此最终结果为9.
因此,返回闭包时牢记:返回函数不要引用任何循环变量,或者后续发生变化的变量
如果一定要引用循环变量,则在创建一个函数,用该函数的参数绑定循环变量当前值,无论循环变量后续如何更改,已经绑定到函数参数的值不变。
def count():
def f(j): #可利用lambda函数简化
def g():
return j*j
return g
fs=[]
for i in range(1,4):
fs.append(f(i))#f(i)立即被执行,因此i的当前值被传入f()
return fs
f1,f2,f3=count() #返回1,4,9