7 Python 基础 装饰器 生成器 迭代器
本节内容:
-
装饰器 介绍 参数
-
生成器 介绍 创建 实现 斐波拉契数列
-
迭代器 介绍 判断是不是迭代器对象 for循环内部做的三件事
装饰器 :(函数)拓展原来还是功能的一种函数,好出就是在不用改原函数代码的前提下给函数增加新的功能。
也就是说 添加新的功能在函数上。
@符号是装饰器的语法糖,在定义函数的时候使用,避免一次赋值操作。
举个列子 老板 写了两个简单的函数 foo() bar() 在不改原代码的基础上计算一下 他们执行了多长时间。
为里执行效果 好看 用time,sleep(2)暂停了 两秒
import time #时间模块
def show_time(f):
def inner():
start = time.time()
f()
time.sleep(2)
end = time.time()
print('spend %s'%(end - start))
return inner
@show_time #@方法 foo = show_time(foo)
def foo():
print('foo......')
#foo()#可以直接执行
@show_time# bar = show_time(bar)
def bar():
print('bar.....')
bar()
装饰器 参数
顺序参数
#顺序参数
import time
def show_time(f):
def inner(x,y):
start = time.time()
f(x,y)
end = time.time()
print('spend %s'%(end - start))
return inner
@show_time
def add(a,b):
print(a + b)
time.sleep(1)
add(1,2)
不定长参数
import time
def show_time(f):
def inner(*x):
start = time.time()
f(*x)
end = time.time()
print('spend %s'%(end - start))
return inner
@show_time
def add(*a):
wk=0
for i in a:
wk +=i
print(wk)
time.sleep(1)
add(1,2,3,5,6,7,7)
功能函数加参数
import time
def logger(flag):
def show_time(f):
def inner(*x,**y):
start = time.time()
f(*x,**y)
end = time.time()
print('spend %s'%(end - start))
if flag == 'true':
print('日志记录')
return inner
return show_time
@logger('true')#想添加日志记录 写true 不像添加 随变写什么
def add(*a,**b):
wk=0
for i in a:
wk +=i
print(wk)
time.sleep(1)
add(1,2,3,5,6,7,7)
2 生成器
什么是生成器 ,通过列表生成式 ,我们可以直接创建一个列表。但是受到内存限制,列表的容量肯定是有限的,而且创建一个包含100万元素的列表,不仅占用空间大,如果我们只访问前面几个元素 后面的空间就白白浪费了,如果列表元素可以通过某种推算出来,那我们就可以通过不断的循环推算出后续的元素,从而节省大量的空间
在Python中,一遍循环一边计算的机制 称为生成器:generator
生成器有两种创建方式 :
1 f = (x*2 for x in range(5)) ()括号
2 yield 关键字
简单的创建 第一种
f = (x*2 for x in range(5)) #创建生成器 循环x 然后乘2 依次打印 print(f) print(next(f))#等价于 f. __next__() 下划线 print(next(f)) print(next(f)) print(next(f))#只能一个一个的取 print(next(f))
生成器就是一个可迭代对象
#生成器就是一个可迭代对象(Ietrable)
f = (x*2 for x in range(5))
for i in f:
print(i)
第二种
#已经不是一个函数了 已经成了生成器对象了 没有进去
#只要有yield就是生成器对象、foo() 是生成器对象
def foo():
print('ok')
yield 1
foo()
#通过next进去
def foo():
print('ok')
abc = yield 1
print(abc)
print('ok2')
yield 2
g = foo()
a = next(g) #可以返看回值的
print(a)
g.send('eee')
#第一次进入不能用send 因为不知道进去传值给谁 可以传入值None
#send 和next都可以进入生成器 不同的是send 可以给里面传值
实现斐波拉契数列
#斐波拉契数列
def fib(max):
n,a,b = 0,0,1
while n < max:
yield b
a,b = b,a+b
n = n + 1
for i in fib(10):
print(i)
迭代器:
生成器都是迭代器 迭代器不一定是生成器
迭代是访问集合元素的一种方法,迭代器是一个可以记住遍历的位置的对象
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束,迭代器只能往前不会后退
什么是迭代器? 满足两个条件:1 有iter方法 2 有 next 方法
我们已经知道,可以直接作用于for循环的数据类型有以下几种 一类是 list tupie dict set str 等;
一类是 generator ,包括生成器和带 yield 的generator function,
这些都可以直接作用于for循环的对象统称为可迭代对象 Iterable 可以使用isinstance()判断一个对象是否是Iterable对象。
for循环内部做的三件事
1 调用可迭代对象的iter方法返回一个可迭代对象
2 不断调用迭代器对象的next方法
3处理stoplteration
l = [1,2,3,4,5,] d = iter(l) print(d) #什么是迭代器? #满足两个条件:1 有iter方法 2 有 next 方法 print(next(d)) print(next(d)) print(next(d)) print(next(d)) print(next(d))
判断
Iterable 可以使用isinstance()判断一个对象是否是Iterable对象
from collections import Iterator
ret1 = isinstance([],Iterator)
print(ret1)
ret2 = isinstance('abc',Iterator)
print(ret2)
ret3 = isinstance((x for x in range(10)),Iterator)
print(ret3)
ret4 = isinstance(8888,Iterator)
print(ret4)
浙公网安备 33010602011771号