迭代器、生成器、装饰器
迭代器和生成器
1、字符串也是可以被for循环,按理说应该是可迭代对象,但是,字符串中并没有遵循迭代器的协议,即没有next方法。
不过,字符串、列表等,是提供了内部的_iter_()方法,把字符串转化为迭代对象,从而遵循迭代器协议,生成可迭代对象。
2、for与迭代器的实现
实质是集合-->__iter__方法-->集合转化为迭代器,并返回地址-->__next__方法调用内容,遵循迭代器协议,生成可迭代对象。
3、迭代器与字典
默认拿到的迭代的内容是集合的key。
4、next内置函数与迭代器
实质上,内置函数next就是在调用 __next__(),next(iter_l) 等价于 iter_l.__next__()
5.、yield
相当于return,但是可以返回多次,得到的就是生成器,自动实现迭代器协议
def test():
yield 1
yield 2
g=test()
print('来自函数',g)
print(g.__next__())
print(g.__next__())
#若再想拿第三个数,会报错,因为只得到了两个生成器
6、生成器(也是一种数据类型)
首先请确信,生成器就是一种迭代器。生成器拥有next方法并且行为与迭代器完全相同,这意味着生成器也可以用于Python的for循环中。另外,对于生成器的特殊语法支持使得编写一个生成器比自定义一个常规的迭代器要简单不少,所以生成器也是最常用到的特性之一。
7、三元表达式
’True时返回的值‘ if 为真时的条件 else False时的条件
例如:‘进来’ if name == 'Harvey' else ‘别进来’
8、列表解析
cattle_list=[]
for i in range(10):
cattle_list.append('牛%s' %i)
print(cattle_list)
l = ['牛%s' %i for i in range(10)] #可以两元
l = ['牛%s' %i for i in range(10) if i >5] #可以改变条件,但不能变成四元表达式,例如不能有else
会生成列表在内存中,处理大数时会占很大内存,列表解析和生成器表达式都是简单的编程方式,生成器表达式更节省内存。
将中括号换成小括号就是生成器表达式
#省内存
niu=('牛%s' %i for i in range(10)) #生成器表达式
print(niu)
print(niu.__next__())
print(niu.__next__())
print(next(niu)) #两者方法相同
print(next(niu))
print(next(niu))
迭代器协议让很多内置函数变得更加通用。例如for,reduce,map,filter,sum
装饰器
装饰器 = 高阶函数 + 函数嵌套 + 闭包
装饰器原则:1、不在源代码上做修改。2、不改变原函数的调用方式
高阶函数:
1.函数接收的参数是一个函数名。2.函数的返回值是一个函数名
满足上述条件任意一个,都可称之为高阶函数
函数嵌套:在一个函数中又定义了一个新的函数
#要求计算原函数的开始执行到结束的时间
import time
def timer(func): #定义一个装饰器的架子
def wrapper(): #架子中的嵌套函数
start_time = time.time() #开始计算时间
res = func() #开始运行传进来的参数,即原函数
stop_time = time.time() #记录结束时间
print('运行时间是%s' %(stop_time - start_time)) #用结束时间-开始时间
return res
return wrapper
————————————————————————————————————以上是装饰器—————————————————————————————————————————
#源代码
def test():
time.sleep(3)
print('运行完毕')
#若想调用装饰器,步骤为:
res = timer(test) #此时返回的是wrapper的地址
#若想执行,则为res(),实际执行的是wrapper()
def test():
time.sleep(3)
print('运行完毕')
res()
#但res()不是我们源代码的调用方式,调用方式应为test()所以应该是
test = timer(test)
#但是在原函数有多个的情况下无法一个个赋值,则有了:
@timer #和test = timer(test)等价,放在源代码上面
#所以若想调用装饰器,正确应为:@装饰器函数名
@timer
def test():
time.sleep(3)
print('运行完毕')
return '这是来自原函数的返回值'
test()