生成器

  • 自定义的迭代器
  • yield关键字: 和return一样,接收值,但不终止函数
def func():
print('from 1')
yield 1
print('form 2')
yield
return 1

func调用之后变成了一个迭代器,yield默认返回None

g = func()
print(g.__next__())
print(g.__next__())
from 1
1
form 2
None

def func():
print('from 1')
yield 1,2
print('from 2')
yield ['a',1,2],2 g = func()
for k,v in g:
print(k,v)
from 1
1 2
from 2
['a', 1, 2] 2

有关yield的理解

一个带有yield的函数,加上括号就是一个生成器,它和普通函数不同,生成生成器时看上去像是调用,但不会执行任何函数代码,直到对其调用next()(在for循环中会自动调用next()) 才开始执行。

虽然执行流程仍按函数的流程执行,但每执行到一个yield语句就会中断,并且返回一个迭代值,下次执行时则从yield的下一个语句继续执行。看上去就像是一个函数在正常执行过程中被yield切割了数次,每次中断都会运行那一段的代码,并且通过yield返回当前的迭代值

yield的好处是把一个函数改写成了一个生成器,就获得了迭代能力,比起用类的实例保存状态来计算下一个next()的值,不仅代码简洁,而且执行流程异常清晰.

而当函数执行结束时,生成器会自动抛出StopIteration 异常,表示迭代完成。在for循环里,无须处理StopIteration 异常,循环会正常结束。

所以有点就是利用迭代,减少内存消耗,让代码更整洁。

在一个 generator function 中,如果没有 return,则默认执行至函数完毕,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代。

实现range()函数


def range(end, start=0, step=1):
count = start
while count < end:
yield count
count += step g = range(10)
print(g.__next__())
print(g.__next__())
print(g.__next__())
0
1
2

更完善的写法

def range(*args):
start = 0
step = 1
if len(args) == 1:
end = args[0]
elif len(args) == 2:
start = args[0]
end = args[1]
elif len(args) == 3:
start = args[0]
end = args[1]
step = args[2]
else:
raise ('传错了')
count = start
while count<end:
yield count
count += step g = range(2,10,2)
print(g.__next__())
print(g.__next__())
print(g.__next__())
2
4
6

生成器表达式

tup = (i for i in range(5))  # 生成了一个老母鸡
print(tup.__next__())
for i in tup:
print(i)
0
1
2
3
4
lis = [i for i in range(5)]  # 生成了一筐鸡蛋
print(lis)
[0, 1, 2, 3, 4]

递归

  • 函数自己调用自己,类似于循环,但这个循环必须有结束条件

思考

def guess_age(count):
count -= 1
if count == 1:
return 26
return guess_age(count)+2
res = guess_age(5)
print(res)
32

斐波那契额

def feib(n):
if n <= 0:
return None
if n == 1 or n == 2:
return 1
else:
return feib(n-1) + feib(n-2) print(feib(10))
55

汉诺塔

def han(n, a, b, c):
if n <= 0:
return None
if n == 1:
print (a,'-->', c)
else:
han(n-1, a, c, b)
han(1, a, b, c)
han(n-1, b, a, c)
han(3, 'a', 'b', 'c')
a --> c
a --> b
c --> b
a --> c
b --> a
b --> c
a --> c

二分法

  • 这种写法是比较通用的,使用in来进行筛选,把第一个值进行比对。
  • 如果是排序好的数列的话,也可以取列表中间的索引的值,使用值的大小来比对
lis = [i for i in range(1000000)]
num = 789433 def erfen(lis, num):
time = len(lis) // 2
if lis[0] == num:
print('找到了')
return None
if num in lis[:time]:
lis = lis[:time]
erfen(lis, num)
elif num in lis[time:]:
lis = lis[time:]
erfen(lis, num)
else:
print('找不到') erfen(lis, num)
找到了

day19-2 生成器,递归函数的更多相关文章

  1. day19 Pyhton学习 递归函数

    # 函数的递归 : 在一个函数的内部调用它自己 # import sys # sys.setrecursionlimit(1000000) # 设置递归的最大深度 # 总结 # 1.递归函数的定义 : ...

  2. 2019-04-01-day023-对象实例的反射实例化

    学习方法 学练改管测 听别人说 读 input 自己说 自己写 output 解决语法错误 解决逻辑错误 ##内容回顾 ##继承 多态 封装 property classmethod staticme ...

  3. Python 第四篇:生成器、迭代器、装饰器、递归函数与正则表达式

    一:生成器:Generator,可以理解为是一种一个函数产生一个迭代器,而迭代器里面的数据是可以通过for循环获取的,那么这个函数就是一个生成器,即生成器是有函数生成的,创建生成器使用()表示,比如g ...

  4. Python开发【第五篇】迭代器、生成器、递归函数、二分法

    阅读目录 一.迭代器 1. 迭代的概念 #迭代器即迭代的工具(自定义的函数),那什么是迭代呢? #迭代:指一个重复的过程,每次重复都可以称之为一次迭代,并且每一次重复的结果是下一个迭代的初始值(例如: ...

  5. day19 生成器+函数递归

    目录 一.yield表达式 1 yield表达式基本用法 二.三元表达式 三.生成式 1 列表生成式 2 字典生成式 3 集合生成式 4 生成器表达式 四.函数的递归 1 递归的定义 2 详解递归 前 ...

  6. day19 生成器函数

    生成器总结: 语法上和函数类似:生成器函数和常规函数几乎是一样的.它们都是使用def语句进行定义,差别在于,生成器使用yield语句返回一个值,而常规函数使用return语句返回一个值. 自动实现迭代 ...

  7. python 生成器等语法

    生成器 调用生成器函数,不会执行生成器函数中的代码,而是返回一个对象,  这个对象是生成器(可用type()函数判断这个对象类型),  如果要运行生成器函数中的代码, 需要调用 next()方法,   ...

  8. python 函数之装饰器,迭代器,生成器

    装饰器 了解一点:写代码要遵循开发封闭原则,虽然这个原则是面向对象开发,但也适用于函数式编程,简单的来说,就是已经实现的功能代码不允许被修改但 可以被扩展即: 封闭:已实现功能的代码块 开发:对扩张开 ...

  9. JS函数相关及递归函数的使用

    JS函数相关及递归函数的使用 通用js程序: function 函数名(参数列表) { 函数体 } 可使用alert()输出,也可用return返回值. alert与return区别: functio ...

随机推荐

  1. python调用函数实现数据的增删改查(1)

    实现一个小功能,当输入相应的序号,会执行相关操作, 比如当输入序号1,会执行添加功能 #coding:utf-8print '''1 添加数据2 删除数据3 修改数据4 查看数据5 退出程序'''de ...

  2. selenium的显示等待和隐式等待区别

    1.selenium的显示等待 原理:显式等待,就是明确的要等到某个元素的出现或者是某个元素的可点击等条件,等不到,就一直等,除非在规定的时间之内都没找到,那么就跳出Exception.(简而言之:就 ...

  3. 小白学习Spark系列三:RDD常用方法总结

    上一节简单介绍了Spark的基本原理以及如何调用spark进行打包一个独立应用,那么这节我们来学习下在spark中如何编程,同样先抛出以下几个问题. Spark支持的数据集,如何理解? Spark编程 ...

  4. python之子类调用父类的两种方式

    第一种方式 直接在子类中调用父类名: Vehicle.__init__(self,name,speed,load,power)#调用父类的实例 Vehicle.run(self) #调用父类的方法 # ...

  5. 训练1-X

    输入n(n<100)个数,找出其中最小的数,将它与最前面的数交换后输出这些数. Input 输入数据有多组,每组占一行,每行的开始是一个整数n,表示这个测试实例的数值的个数,跟着就是n个整数.n ...

  6. BZOJ 3158 千钧一发 (最大流->二分图带权最大独立集)

    题面:BZOJ传送门 和方格取数问题很像啊 但这道题不能像网格那样黑白染色构造二分图,所以考虑拆点建出二分图 我们容易找出数之间的互斥关系,在不能同时选的两个点之间连一条流量为$inf$的边 由于我们 ...

  7. phpunit使用

    phpunit使用 标签(空格分隔): php 现在是凌晨 3 点.我们怎样才能知道自己的代码依然在工作呢? Web 应用程序是 24x7 不间断运行的,因此我的程序是否还在运行这个问题会在晚上一直困 ...

  8. ubuntu 下jrtplib编译

    我本来想用最新的 jrtplib-3.9.1和jthread-1.3.1,可是最新的那两个版本中都是用cmake进行配置的,我搞了好久,查了好多资料也没有解决交叉编译的问题,无奈,只能选用比较老的两个 ...

  9. 简洁又快速地处理集合——Java8 Stream(下)

    上一篇文章我讲解 Stream 流的基本原理,以及它与集合的区别关系,讲了那么多抽象的,本篇文章我们开始实战,讲解流的各个方法以及各种操作 没有看过上篇文章的可以先点击进去学习一下 简洁又快速地处理集 ...

  10. BA-siemens-insight在win7下如何配置opc接口

    一.运行环境:win7(OPC接口在win_xp下配置需安装插件,不好意思没搞定,现在只有win7系统32位下的教程了) 由于OPC(OLE for Process Control)建立在Micros ...