博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python基础(八)生成器,迭代器,装饰器,递归
阅读量:6879 次
发布时间:2019-06-26

本文共 4396 字,大约阅读时间需要 14 分钟。

生成器

在函数中使用yield关键字就会将一个普通的函数变成一个生成器(generator),普通的函数只能使用return来退出函数,而不执行return之后的代码.而生成器可以使用调用一个next方法来返回生成器中上一次yield时候的状态.并且可以使用send方法给yield重新赋值.这样就可以灵活的进入和跳出函数.因此在程序中生成器可以中断当前函数,去执行其它的代码,在合适的时候跳回函数继续执行

def yield_test():    print('befor the first')    first = yield    print(first)    print('before the second')    second = yield    print(second)    print('before the Third')    Third = yield '也可以有返回值'    print(Third)    print('after the Third')    #next方法g = yield_test()g.__next__()g.__next__()yield_text = g.__next__()       #获取yield传出的数据,接受数据next和发送数据yield的位置顺序相同print(yield_text)# g.__next__()#send方法g = yield_test()g.__next__()                    #做实验时第一次必须是next,send会报错g.send('2222')                  #send发送的数据会被赋值给当前yield之前的代码中生效.                                #简单说是赋值给前一个yield以便本次代码执行g.send('3333')

补充:通过这个例子我们发现

1,send方法被生成器当作了一次__next__,并且send的值会复制给上一个yield,
2,yield和__next_方法是一一对应.当next比函数内yield多时,最后一个next会报一个StopIteration异常.
3,yield后的代码会在下一次next调用时才会执行.
4,yield可以发送数据,也可以接受数据.获取数据时要注意传入和传出不同时机才能获取正确的yield值

所以我们通常把生成器用在可循环的对象

def read_file():    read_size = 10    with open('test.txt','rb') as f:        while True:            text = f.read(read_size)            yield text      #通过yield获取当前的text值g = read_file()         while True:    print(g.__next__())#生成器这样使用会进入一个死循环

补充:

5, 生成器必须要有明确的退出条件,为了不造成死循环. 所以慎用循环.

def read_file():    read_size = 10    with open('test.txt','rb') as f:        while True:            text = f.read(read_size)            if text:                #判断文件是否读取完毕                yield text                  else:                returng = read_file()         while True:    print(g.__next__())

迭代器

iterable(可迭代对象)可以直接作用与for循环的对象.可迭代对象分为:一,集合数据类型如:str字符串,list列表,dict字典,tuple元组,set集合等.二,生成器generator和带yield的函数.判断是否为iterable对象可以使用函数isinstance().

在python中list等集合数据类型是非常占用内存的,通过使用iter()可以将一个可迭代对象变成一个迭代器.迭代器中不存储具体数据,只是保存了产生这种数据的逻辑对象.在使用时才产生需要的数据,可以大大节省空间.

from collections import Iteratorlist = []for i in range(10):    list.append(i)print(list,isinstance(list,Iterator))list_Iterator= iter(list)print(list_Iterator,isinstance(list_Iterator,Iterator))for i in list_Iterator:    print(i)

补充:

1, 迭代器中并没有保存真正的数据,只有在我们去通过next方法去迭代器中取数据
2, 迭代器中是按照一定的顺序输出所有数据,不能取指定的数据.

装饰器

装饰器(decorator)是一种函数的高级用法,主要是通过高阶函数和返回函数组合的方式,修饰其它函数.达到被修饰的函数代码不用修改,调用方式也不变的目的.主要作用就是给被修饰的函数添加功能.

  • 原函数不带参数
#假如有这么三个函数,我们需要记录访问时间和函数名,但是又不能修改函数def home():    print('index page')def bbs():    print('bbs page')def news():    print('news page')home()bbs()news()
#加上装饰器后的效果import timelog_list = []def user_log(func):     #将被装饰函数作为参数传入user_log这个装饰器    def wrapper():      #触发执行装饰器的函数        func()          #在装饰器内执行原函数        log_time = time.strftime("%Y-%m-%d %H:%M:%S")   #装饰器内具体新代码        page_name = func.__name__        log_page = str(log_time+'  ->'+page_name)        log_list.append(log_page)    return wrapper      #将触发函数返回,一定不要加()执行符号@user_logdef home():    print('index page')@user_logdef bbs():    print('bbs page')@user_logdef news():    print('news page')home()bbs()news()print(log_list)
  • 带参数的函数
计算函数运行时间的装饰器import timedef time_consum(func):    def wrapper(*args,**kwargs):        start_time = time.time()        func(*args,**kwargs)        print('running',time.time()-start_time)    return wrapper@time_consumdef user_profile(username):    time.sleep(3)    print('welcome %s'%username)user_profile('sylar')
  • 装饰器带参数,
#根据装饰器参数执行不同的功能import timelog_list = []def change_type(ch_type='other'):    def decorator(func):        def wrapper(*args,**kwargs):            if ch_type == 'tc':                start_time = time.time()                func(*args,**kwargs)                print('running',time.time()-start_time)            else:                func()                print('other type code')                log_time = time.strftime("%Y-%m-%d %H:%M:%S")  # 装饰器内具体新代码                page_name = func.__name__                log_page = str(log_time + '  ->' + page_name)                log_list.append(log_page)        return wrapper    return decorator@change_type()def home():    print('index page')@change_type('tc')def user_profile(username):    time.sleep(3)    print('welcome %s'%username)home()user_profile('sylar')print(log_list)

递归函数

在函数内部,调用了这个函数自己.就叫做递归函数

#直接使用递归法求解斐波那契数量的第num个数字def fib(num):    if num<2:        return num    return fib(num-1)+fib(num-2)for i in range(10):    print(fib(i))

补充递归函数必须要有一个明确的结束条件,python中支持最大递归次数1000

转载于:https://www.cnblogs.com/ops-sylar/p/8183687.html

你可能感兴趣的文章
STAR法则
查看>>
sprintf介绍
查看>>
java学习:weblogic下JNDI及JDBC连接测试(weblogic环境)
查看>>
python invoke super parent method
查看>>
[LeetCode] Binary Tree Maximum Path Sum
查看>>
获取HTML源码(只取文字,判断编码,过滤标签)
查看>>
我的架构经验系列文章 - 后端架构 - 设计层面
查看>>
vc生成静态库例子
查看>>
那些帮助你成为优秀前端工程师的讲座——《CSS篇》
查看>>
CheckBox为CheckBoxList实现全选或全取消选择
查看>>
Windbg中使用查找内存并设置访问断点
查看>>
数据库分区表的使用
查看>>
【SAS NOTES】_NULL_
查看>>
辨别delegate方法的好办法
查看>>
C#实现的几种委托
查看>>
Hypertable 0.9.7.1 发布,分布式数据库
查看>>
PHP获得真实客户端的真实IP REMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR
查看>>
poj1323
查看>>
c getline
查看>>
linux下拷贝的时候有时候会出现cp:omitting directory的错误
查看>>