12.python编程函数之——三大神器:装饰器,迭代器,生成器

一、装饰器

不改变源代码调用方式的基础之上给函数增加新的功能
我们来看下面的代码 :

def deco(func):#func = index
    def wrapper(): #wrapper() = index()
        func() #func() = index()
        print('增加新功能')
    return wrapper

@deco  #index = deco(index)
def index():
    print('欢迎来首页')
index() #index = wrapper
输出:
欢迎来首页
增加新功能

通过打断点Debug体会它的运行过程:

  1. 首先解释器光影打到第一行将要执行还未执行,解释器检测到是一个定义的函数选择跳过执行函数之后的内容;
  2. 解释器光影打到第7行,通过@deco知道index=deco(index),函数deco是一个装饰器并返回执行deco()这个函数;
  3. 当解释器执行到第二行又发现wrapper也是一个函数且当前没有调用这个函数就不会执行wrapper函数体里的代码,解释器会直接执行return
    wrapper,那么这时函数deco()执行结果就等于函数wrapper的内存地址,即:deco(func)=wrapper;
  4. 这时再(step over)单步执行光影又会回到@deco,这时由index=deco(index)和deco(func)=wrapper得出index=wrapper,它俩的内存地址是相等的;
  5. 再单步执行解释器会直接找到index()并执行调用index()函数,而调用index()函数就等于调用wrapper()函数,解释器光影会返回执行wrapper()函数;
  6. 当执行到func(),之前由index=deco(index)和deco(func)=wrapper得出index=wrapper时还能得出func=index,所以执行func()函数就等于执行index();
  7. 解释器会去执行index()函数,首先输出‘欢迎来首页’这5个字,然后会回到func()再执行输出‘增加新功能’就全部执行完毕。

有参装饰器

def deco(func):
    def wrapper(username,password):
        if username == 'root' and password == 'root':
            func(username,password)  #test()  print('this is test func')
        else:
            print('用户名或密码错误')
    return wrapper
@deco
def aaa_index(username,password):
    print('welcome to aaa')
aaa_index('root','root')

@deco
def bbb_index(username,password):
    print('welcome to bbb')
bbb_index('root','root')
输出:
welcome to aaa
welcome to bbb

二、迭代器

  • 迭代是一个重复的过程,即每一次重复为一次迭代
  • 每次迭代的结果都是下一次迭代的初始值
 -l = [1,2,3]
count=0
while count<len(l): #首先是重复动作,其次上一次的结果是下一次的初始值,因此,是迭代
    print(l[count])
    count+=1
1.为何要有迭代器?

对于序列类型:字符串、列表、元组,我们可以使用索引的方式迭代取出其包含的元素。但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则 必须找出一种不依赖于索引的迭代方式,这就是迭代器。

l1 = [1,2,3]   #列表
t1  = (1,2,3)  #元组
str1 = '123'   #字符串
s1 = {1,2,3}   #集合
d1 = {'name':'aaa','age':'bbb'}    #字典
f = open('a.txt','r',encoding='utf-8')   #文件

整型和浮点型没有任何方法

num1 = 10   
num2 = 12.2
2.什么是可迭代对象?

目标对象有._iter_方法的都叫做可迭代对象

l1._iter_()
t1._iter_()
str1._iter_()
s1._iter_()
d1._iter_()
f._iter_()
3.什么是迭代对象?

目标对象有._iter_和._next_方法的叫做迭代器对象

f._iter_()
f._next_()

文件就是一个迭代对象,而列表、元组、字符串、集合、字典需要通过iter()转化成迭代器对象

res1 = iter(l1)
res2 = iter(t1)
res3 = iter(str1)
res4 = iter(s1)
res5 = iter(d1)
res1.__iter__() 
res1.__next__()
res2.__iter__() 
res2.__next__()
res3.__iter__() 
res3.__next__()
res4.__iter__() 
res4.__next__()
res5.__iter__() 
res5.__next__()

实际正真迭代对象已经变成res1,res2,res3,res4,res5

例:如果我们不用for循环打印出l1列表的元素,那么可以转化成迭代器对象后就可以循环出元素

l1 = [1,2,3]
res1 = iter(l1)
print(next(res1))
print(next(res1))
print(next(res1))
输出:
1
2
3

如果再加一行print(next(res1))就会报错,因为元素只有三个
其实用for循环出l1列表的元素很简单,而我们不知道for其实内部帮我们做了一些处理

for的作用:

  1. 把可迭代对象变成迭代器对象,例:iter(l1)
  2. 过滤错误信息

例:for循环出l1列表的元素

l1 = [1,2,3]
for i in l1:  #iter(l1)
    print(i)
输出:
1
2
3

注意:迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象

三、生成器

1.只要函数里有yield关键字,函数名()得到的结果就是生成器,生成器就是迭代器,并且不会执行函数内部代码

2.return只能返回一个值,而yield可以返回多个值

3.生成器优缺点:

  • 优点:同一时间只存储一个值,节省内存空间
  • 缺点:只能向后取值,不能往前取值

例:

def test():
    for i in range(100):
        yield i
res = test()

for k in res:
    print(k)
结果将打印0-99的数
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值