3、装饰器、迭代器、生成器
>>>>>>>>>>>>>>>装饰器<<<<<<<<<<<<<<
1、什么是装饰器
装饰器就是一个用来为被装饰对象添加新功能的工具
2、为何要用装饰器
开放封闭原则:一旦软件上线运行之后,应对需改的源代码封闭,对扩展功能开放
原则:
1、不修改函数内的源代码
2、不修改函数的调用方式
装饰器就是在遵顼原则1和2的前提下,为被装饰对象添加新功能
3、如何实现装饰器
需求:为函数index添加运行时间的功能
源代码:
import time
def index():
time.sleep(1)
print('你真帅')
index()
装饰器装饰:
import time
def index():
time.sleep(1)
print('你真帅') 源代码不变
开始装饰
1 def outter(func): func =被装饰对象 index函数的内存地址
2 def wrapper(*args,**kwargs):
3 start time.time()
4 res = func(*args,**kwargs) 被装饰对象index函数的内存地址(x,y,z)
5 stop time.time()
6 print(('run time is %s')%(stop - start))
7 return res 返回结果也做到和 index 一样
8 return wrapper
9 index = outter(index) outter(被装饰对象index函数的内存地址) -> 返回wrapper函数的内存地址 -> index = wrapper函数的内存地址
10 index() 调用方式不变 表象是index本质上是wrapper
>>>>>>>>>>装饰器语法糖<<<<<<<<<<<<
装饰器语法糖是装饰器的,为了更简单漂亮的使用装饰器
import time
from functools import wraps 将wrapper的一些其他参数 也都变成index 更完美的装饰index 和 @wraps 一起使用
def outter(func): # func = 被装饰对象index函数的内存地址
@wraps(func)
def wrapper(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs) # 被装饰对象index函数的内存地址(x,y,z)
stop = time.time()
print('run time is %s' %(stop - start))
return res
return wrapper # 千万别加括号
@outter # index = outter(index) # outter(被装饰对象index函数的内存地址) -> 返回wrapper函数的内存地址---> index = wrapper函数的内存地址
def index(): # index = 被装饰对象index函数的内存地址
"""这是index函数"""
time.sleep(1)
print('from index')
@outter # home = outter(home)
def home(name):
time.sleep(2)
print("welcome %s to home page" %name)
return 123
无参装饰器的模板 记住就好
def outter(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper
例 :登录程序
def login(func):
def wrapper(*args,**kwargs):
name = input('name>>>>':)
pwd = input('pwd>>>>>:')
if name == 'liu' and pwd == '123':
res = func(*args,**kwargs)
return res
return wrapper
@login
def index():
print('index')
index()
>>>>>>>>迭代器<<<<<<<<<
1、什么是迭代器
迭代器就是指迭代取值的工具
####什么是迭代?
迭代就算一个重复取值的过程,但是每一次都在上一次的基础上进行的
比如:
nums = [111,22,333]
def get(l):
i = 0
while i < len(l)
print(l[i])
i += 1
get(mus)
看到这个有木有想到什么。没错 就是之前的 for 遍历循环,for 循环的本质就是运用迭代器
2、为何要用迭代器
####1、迭代器提供了一种不依赖于索引的、通用的迭代取值方案
####2、节省内存
3、如何用迭代器
####可迭代的对象
1、内置有__iter__方法的对象都叫可迭代的对象
调用可迭代对象的__iter__方法,返回的是它的迭代器
####迭代器对象
1、内置有__next__方法
2、内置有__iter__方法
调用迭代器对象的__iter__方法得到的它自己,就跟没调用一样
调用迭代器对象的__next__方法返回下一个值,不依赖索引
可以一直调用__next__直到取干净,则抛出异常StopIteration
内置的 类型都是可迭代对象
字符串str 列表list 字典dict 集合set 元组tuple
文件本身就是一个迭代器
在使用while迭代对象的时候
nums_iter = iter(nums)
while True:
try:
res = next(nums_iter)
print(res)
except StopIteration: # 取完结束 防止报错崩溃
break
而 for 的强大在于包含了这些内容
1、先调用in后那个对象的__iter__方法,拿到迭代器对象
2、 res = next(迭代器对象),执行一次循环体代码
3、循环往复步骤2,直到值取干净抛出异常StopIteration,for会捕捉异常结束循环
for res in nums:
print(res)
<<<<<<<<<<生成器>>>>>>>>>>
在使用函数的时候 使用return 可以提返回值 但是return 只能返回一次,后面程序会停止运行
但是有个一函数 yield 可以返回多次,可以暂停函数的运行!!!!
yield 与 return的异同
相同点:返回值层面用法一样
不同点:return只能返回值一次,而yield可以返回多次
比如
def func():
print('xxx')
yield 111
print('yyy')
yield 222
print('zzz')
yield 333
print('mmmm') 最后一行代码mmm 不会被打印出来
当函数内出现yield关键字,再调用函数并不会触发函数体代码的运行,会返回一个生成器
g = func()
print(g) # 生成器就是一种自定义的迭代器
使用yield 造成一个无限循环的老母鸡 不占用大量空间
def func():
res = 1
while True:
yield res
res += 1
g = func()
print(next(g))
print(next(g)) 取一次 只取一个数 就会遇到 yield 暂停
扩展
nums =[111,22,33]
x = iter(nums) x= 迭代器
for res in x: # x.iter()是返回本身,循环完了
print(res)
print('='*50)
for res in x: # x.iter() 所以本次不会再取到数
print(res)
for res in nums: # nums.iter()是生成一个迭代器
print(res)
print('='*50)
for res in nums: # nums.iter()又生成一个新的迭代器
print(res)
路漫漫其修远兮,吾将上下而求索!!!
加油吧!