生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写__iter__()和__next__()方法了,

只需要一个yiled关键字。 生成器一定是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。

deffunc():

print('====>first')

yield 1

print('====>second')

yield 2

print('====>third')

yield 3

print('====>end')

g=func()

print(g)

next(g)

next(g)

next(g)

输出结果

====>first

====>second

====>third

生成器

凡是函数体内存在yied关键,调用函数体不会执行函数体代码,会得到一个返回值,该返回值就是生成器对象

需要提示的是,生成器是一个特殊的迭代器

next的功能就是为了触发函数体的执行

yied可以让函数暂停在本次循环的位置,当再有next调用触发时,就会继续本次调用的位置继续往下执行,如此循环往复。

实例:生成器对象

def func():

print('first')

yield 1#1是自己定义的yied返回值

g=func()

print(g)

输出结果:

实例:生成器对象调用

def func():

print('first')

yield 1#1是自己定义的yied返回值

print('second')

yield 2

print('third')

yield 3

g=func() #这里是一行代码都没有运行,如果想要触发生成器,就需要调用next的方法,g呢是一个函数,

# 也将会触发g函数体内的代码执行,

res1=next(g)#会触发函数的执行,直到碰到一个yied停下来,并且将yied后的值当作本次next的结果返回

# 迭代器调用next会返回一个值,可以将值赋值给一个变量res,res只是第一次迭代返回的值

# 过程:

#1.next防止调用

# 2.g函数体内代码执行,遇到第一个yied停止,并返回结果

res2=next(g)#第二次# 迭代,返回res2

自定义一个跟内置的range函数一样的生成器

def my_range(start,stop,step):

while start < stop:

yield start

start +=step

取值方式1,使用迭代器,next触发函数运行,一个个的取出,要多少取多少,不会浪费内存空间,

再大的数字也不会担心内存溢出,但是for循环取值的话,是一次性取出范围内所有的值,如果超过容器最大的范围

会造成内存溢出

g=my_range(1,10,1)

res1=next(g)

print(res1)

res2=next(g)

print(res2)

res3=next(g)

print(res3)

res4=next(g)

print(res4)

取值方式2,使用for循环

for i in my_range(1,100000000,1):

print(i)

列表,每个元素都存在列表里

g1=[x*x for x in range(10)]

print(g1)

生成器,是一个可以产生出列表元素的算法工具,在使用时,才能产生需要的列表元素。

使用方式:

1.直接使用next()进行调用,因为生成器本身就是一个迭代器,拥有__iter__和__next__内置方法

2.可以使用for循环把生成器内的元素遍历出来,for循环使用的就是__iter__和__next__同样的机制

g2 = (x*x for x in range(10))

print(g2)

输出对比

[p1, 1, 4, 9, 16, 25, 36, 49, 64, 81]

at 0x010EE2D0>

案例1

斐波那契数列:

def fib1(max):

n,a,b=p1,p1,1

while n < max:

print(b)

a,b=b,a+b

n = n + 1

return 'done'#函数的返回值,给出函数执行的最后的结果,可以不写,但是最好带上,以免产生不必要的麻烦

fib1(10)#调用函数,执行函数体内的代码

print(fib1.__name__)#函数名字

print(fib1)#函数的内存地址

改写成生成器的方式:

def fib2(max):

n,a,b=p1,p1,1

while n

yield b

a,b=b,a+b

n = n + 1

return 'done'

f=fib2(10)#接收fib的生成器的返回值,yied的返回值定义的是b,下次next操作时是接着本次循环往后接续取值。

#第一次取值

res1=next(f)

print(res1)

#第二次取值

res2=next(f)

print(res2)

for i in fib2(6):

print(i)

案例2

def odd():

print('step 1')

yield 1 #第一次取值时,遇到yied中断,返回值为1

print('step 2')

yield(3) #第二次取值时,继续第一次中断的地方继续往下执行,

# 遇到第二个yied时中断,完成了第二次的取值,返回值3,依次进行

print('step 3')

yield(5)

o=odd()

next(o) #第一次

next(o) #第二次

next(o) #第三次

next(o)#第四次取值时因为超出了范围就报错

yied表达式形式的应用

x=yield #yied 的表达式形式

.send()#给yied传值

实例

针对yied表达式的使用,

第一步:

现使用next将函数停在yied的位置,

或者使用‘,send(None)’传一个none得值给yied,如果第一次没有传空值,就会有如下报错

def func(name):

print("%s往前跳"%name)

while True:

num=yield

print("%s往前跳了%s步"%(name,num))

f=func('joke')

输出结果

f.send(2)

f.send(2)

TypeError: can't send non-None value to a just-started generator

第二步:使用‘.send’给yied传值

第三步:使用next就可以使停在yied的位置的函数进行往下运行,while循环再次停在yied的位置

然后再‘.send’给yied传值,往复循环,就会源源不断的有值进去。

注:‘,send’本身就有next的功能,当传完值后,无需使用next,即可继续往下走

def func(name):

print("%s往前跳"%name)

while True:

num=yield

print("%s往前跳了%s步"%(name,num))

f=func('joke')

next(f)

f.send() #第一次传值,必须传空值none

f.send(2)

f.send(4)

总结:

1.yied只能在函数内使用

2.yied提供了一种自定义迭代器的解决方案

3.yied可以保存函数的暂停状态

4.yied与return

相同之处都可以返回值,值得类型和个数都没有限制

不同之处,yied可以返回多次值,return只能返回一次值

生成器表达式

l=[1,2,3,4]#列表生成式

l=(1,2,3,4)#生成器表达式,把[]换成()即可

实例

注:生成器对象在没有进行next调用时是没有进行yied执行的,即不使用不触发;不next不执行

生成器内部不存值,值是内部在每次调用时制造出来。

g=(i**2 for i in range(1,5) if i>3)

print(next(g))#停在第一次满足i>3后获得的i值处,i=4

print(next(g))#第二次进行yied操作,满足条件,停在i=5的地方

print(next(g))#第三次进行next操作的时候,已超过了范围内,就会报错,停止执行

注:为了不导致内存溢出,使用生成器

实例:

统计文件内的字符数

方式1

with open('今日内容','rt',encoding='utf-8') as f:

data=f.read()

print(len(data))

问题:所有文本的内容全部读取到内存,如果文件过大,将会导致内存不够使用,进而导致内存溢出

方式2

with open('今日内容','rt',encoding='utf-8') as f:

res=0

for line in f:

res +=len(line)

print(res)

问题:是没导致内存溢出,因为是一行一行的进行读取的,但是使用了for自己定义的循环,繁琐了很多

方式:3

with open('今日内容','rt',encoding='utf-8') as f:

print(sum(len(line) for line in f))

生成器表达式:(len(line) for line in f) #生成器对象

再使用sum内置函数求和sum()

面试关于生成器实例:

def add(n,i):

return n+i

def test():

for i in range(4):

yield i

g=test()

for n in [1,10]: #n=10

g=(add(n,i) for i in g)

分析:

第一次循环:

n=1,没有触发生成器对象的函数体代码,整个的函数的代码,将原封不动的传给g

g=(add(n,i) for i in test())

test中i=p1,1,2,3

n+i=10,11,12,13

g=(10,11,12,13)

第二次循环:

n=10时 next,触发了函数体里的代码

g=(add(n, i) for i in (add(n,i) for i in test()))

(add(n,i) for i in test())=(10,11,12,13)

n+i=20,21,22,23

g=(20,21,22,23)

print(n)

res=list(g)

迭代器1=(add(n,i) for i in test())

for i in 迭代器1: #i=next(迭代器1) i=11

add(n, i) #add(10,11)

A. res=[10,11,12,13]

B. res=[11,12,13,14]

C. res=[20,21,22,23]

D. res=[21,22,23,24]

答案:c

生成器在Python中是一个非常强大的编程结构,可以用更少地中间变量写流式代码,此外,相比其它容器对象它更能节省内存和CPU,当然它可以用更少的代码来实现相似的功能。

import time

def genrator_fun1():

a = 1

print('现在定义了a变量')

yield a

b = 2

print('现在又定义了b变量')

yield b

g1 = genrator_fun1()

print('g1 : ',g1) #打印g1可以发现g1就是一个生成器

print('-'*20) #我是华丽的分割线

print(next(g1))

time.sleep(1) #sleep一秒看清执行过程

print(next(g1))

输出结果

g1 :

--------------------

现在定义了a变量

1

现在又定义了b变量

2

生成器有什么好处呢?就是不会一下子在内存中生成太多数据

def produce():

"""生产衣服"""

for i in range(2000000):

yield "生产了第%s件衣服"%i

product_g = produce()

print(product_g.__next__()) #要一件衣服

print(product_g.__next__()) #再要一件衣服

print(product_g.__next__()) #再要一件衣服

num = 0

for i in product_g: #要一批衣服,比如5件

print(i)

num +=1

if num == 5:

break

#到这里我们找工厂拿了8件衣服,我一共让我的生产函数(也就是produce生成器函数)生产2000000件衣服。

#剩下的还有很多衣服,我们可以一直拿,也可以放着等想拿的时候再拿

def produce():

"""生产衣服"""

for i in range(2000000):

yield "生产了第%s件衣服"%i

product_g = produce()

print(product_g.__next__()) #要一件衣服

print(product_g.__next__()) #再要一件衣服

输出结果

生产了第0件衣服

生产了第1件衣服

生成器本质也是一个迭代器,当我们一次次的索要产生的值时,,每次遇到yield就会停止一下,返回值和生成结果,再次索要下次的值时就会重复的进行相同的操作。

def produce():

"""生产衣服"""

for i in range(2000000):

yield "生产了第%s件衣服"%i

product_g = produce()

print(product_g.__next__()) #要一件衣服

# print(product_g.__next__()) #再要一件衣服

# print(product_g.__next__()) #再要一件衣服

# print(product_g.__next__()) #再要一件衣服

# print(product_g.__next__()) #再要一件衣服

# print(product_g.__next__()) #再要一件衣服

# print(product_g.__next__()) #再要一件衣服

num = 0

for i in product_g: #要一批衣服,比如5件

print(i)

num +=1

if num == 5:

break

输出结果

生产了第0件衣服

生产了第1件衣服

生产了第2件衣服

生产了第3件衣服

生产了第4件衣服

生产了第5件衣服

python done()函数_python之函数相关推荐

  1. 在python中使用关键字define定义函数_python自定义函数def的应用详解

    这里是三岁,来和大家唠唠自定义函数,这一个神奇的东西,带大家白话玩转自定义函数 自定义函数,编程里面的精髓! def 自定义函数的必要函数:def 使用方法:def 函数名(参数1,参数2,参数-): ...

  2. python神秘的魔法函数_Python魔法函数

    1.什么是魔法函数 魔法函数即Python类中以__(双下划线)开头,以__(双下划线)结尾的函数,Python提供的函数,可让咱们随意定义类的特性 示例: class Company(object) ...

  3. python del函数_python del函数是什么以及如何使用?

    这是关于Python里比较难得一个函数,甚至于章节不多,但是讲的内容却很多很多,大家对部分内容不知道有没有过了解--面向对象,而在这里主要用到的函数就是del,大家如果不知道的话,可以跟随小编一起来看 ...

  4. python中模块和函数_Python中函数和模块的体验与使用

    函数基础 目标 函数的快速体验 函数的基本使用 函数的参数 函数的返回值 函数的嵌套调用 在模块中定义函数 01. 函数的快速体验 1.1 快速体验 所谓函数,就是把 具有独立功能的代码块 组织为一个 ...

  5. python反序数函数_python range()函数取反序遍历sequence的方法

    python range()函数取反序遍历sequence的方法 python中的range函数取反序有两种方式 第一种:先构建一个列表,然后对列表中的元素进行反转. 例如: a=range(5) f ...

  6. python用psf函数_Python 嵌套函数(高级用法)

    Python 嵌套函数(高级用法) 一.嵌套函数(高级用法) 1.嵌套函数 函数的嵌套调用是在"函数调用中再调用其他函数".也就是说:函数嵌套允许在一个函数中调用另外一个函数.如下 ...

  7. python asyncio回调函数_python回调函数用法实例分析

    python回调函数用法实例分析 本文实例讲述了python回调函数用法.分享给大家供大家参考.具体分析如下: 软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用.回调和异步 ...

  8. python引用函数_python 调用函数

    Python内置了很多有用的函数,我们可以直接调用. 要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个参数.可以直接从Python的官方网站查看文档: 也可以在交互式命令行 ...

  9. python中的get函数_python之函数用法get()

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python之函数用法get() #http://www.runoob.com/python/att-dic ...

  10. python reduce函数_Python reduce()函数的用法小结

    reduce()函数也是Python内置的一个高阶函数. reduce() 格式: reduce (func, seq[, init()]) reduce()函数即为化简函数,它的执行过程为:每一次迭 ...

最新文章

  1. 人工智能(5)---一文解读人工智能创业的5大坑
  2. 电动力学每日一题 2021/10/14
  3. 论文笔记:Image Caption(Show and Tell)
  4. 统计学习方法第十五章作业:SVD矩阵分解 代码实现 及其在推荐的应用和矩阵压缩意义
  5. 量子计算机超越传统计算机位数,量子计算机相对于传统的计算机有着怎样的优势?...
  6. 微软提高 Microsoft 365 的漏洞奖励
  7. c c++ 宏定义中#, ##, #@的含义
  8. python中常用的数据结构简述
  9. [Android] 选项卡组件TabHost
  10. 批量下载中国气象科学数据共享网的数据
  11. [FAQ06649] Latin输入法怎么默认勾选几种语言?
  12. RGB与CMYK这两大色彩模式的区别
  13. PageHelper.startPage 的作用范围探究
  14. 如何申请注册Tom企业邮箱,教程详解来袭
  15. Android jks文件签名转换keystore文件签名
  16. html的弯曲的虚线设置,Photoshop如何画出弯曲的虚线?
  17. windows11 文档背景设置护眼色
  18. AM335x硬件开发使用指南(一)
  19. CPU大小端模式对C语言底层开发的影响
  20. 解决 plt.savefig() 生成空白图片的问题

热门文章

  1. Linux/Centos 安装oracle报错“调用makefile '/oracle/produc
  2. vsftp用户设置目录访问权限
  3. android系统源码7.1.2_r8下载,编译,运行到nexus5X上,修改源码并编译SDK进行测试
  4. 中间件安全之GlassFish
  5. 量化指标WR:弱的确是弱,但是老Q会魔改啊!
  6. 【C语言】专升本招生考试《C语言程序设计》试题
  7. 2020新东方文都考研数学、英语、政治辅导班SVIP视频持续更新
  8. 计算机操作重复的词语,怎么查找Word文档重复词语
  9. java 设置热键_Java设置全局热键——第三方包jintellitype实现
  10. winform窗体热键设置