Python之函数进阶-生成器函数

Python之函数进阶-生成器函数

生成器函数

  • Python中有2种方式构造生成器对象:
    • 生成器表达式
    • 生成器函数
      • 函数体代码中包含yield语句的函数
      • 与普通函数调用不同,生成器函数调用返回的是生成器对象

普通函数调用,函数会立即执行直到执行完毕。

生成器函数调用,并不会立即执行函数体,而是返回一个生成器对象,需要使用next函数来驱动这个生 成器对象,或者使用循环来驱动。

生成器表达式和生成器函数都可以得到生成器对象,只不过生成器函数可以写更加复杂的逻辑。

  • 函数返回
    • return语句依然可以终止函数运行,但return语句的返回值不能被获取到
    • return会导致当前函数返回,无法继续执行,也无法继续获取下一个值,抛出StopIteration 异常
    • 如果函数没有显式的return语句,如果生成器函数执行到结尾(相当于执行了return None),一样会抛出StopIteration异常

生成器函数

  • 包含yield语句的生成器函数调用后,生成生成器对象的时候,生成器函数的函数体不会立即执行
  • next(generator) 会从函数的当前位置向后执行到之后碰到的第一个yield语句,会弹出值,并暂停 函数执行
  • 再次调用next函数,和上一条一样的处理过程
  • 继续调用next函数,生成器函数如果结束执行了(显式或隐式调用了return语句),会抛出 StopIteration异常

python 复制代码
int('a', 16)

#具体解释如下:
#int() 是Python内置的数值类型转换函数,用于将其他类型的数据转换为整数。
#'a' 是一个十六进制字符串,表示要进行转换的值。
#16 是指定了输入字符串的进制数,这里表示十六进制。
#因此,int('a', 16) 的作用是将十六进制字符串 'a' 转换为对应的十进制整数。在十六进制中,字符 'a' 
#对应的十进制值为 10。所以,执行该代码后,会返回结果 10。

# 返回结果:10
python 复制代码
x = ['a', 1, 'b', 20, 'c', 32]
print(sorted(x, key=str))

# 定义一个列表,打印列表的值,转换成str格式进行排序
# 返回结果:[1, 20, 32, 'a', 'b', 'c']
python 复制代码
# 定义一个列表x,包含字符串和整数
x = ['a', 1, 'b', 20, 'c', 32]
def fn(x):	# 定义一个函数fn,用于处理列表中的元素
    if isinstance(x, int):	# 如果元素是整数,直接返回该整数
        return x
    else:
        return int(x, 16)	# 如果元素是字符串,尝试将其转换为十六进制整数并返回

print(sorted(x, key=fn))	# 使用sorted函数对列表x进行排序,key参数指定排序依据为fn函数的返回值

# 这样,列表中的字符串元素会按照其对应的十六进制整数值进行排序
# 返回结果:[1, 'a', 'b', 'c', 20, 32]
python 复制代码
x = ['a', 1, 'b', 20, 'c', 32]
def fn(x):
    return x if isinstance(x, int) else int(x, 16) # 三元表达式写法

print(sorted(x, key=fn))

# 返回结果:[1, 'a', 'b', 'c', 20, 32]
python 复制代码
x = ['a', 1, 'b', 20, 'c', 32]

print(sorted(x, key=lambda x: x if isinstance(x, int) else int(x, 16)))

# lambda表达式
# 返回结果:[1, 'a', 'b', 'c', 20, 32]

生成器函数总结

  • 生成器对象
    • 生成器表达式, 每一次生成器表达式执行一次都会得到一个全新的生成器对象
    • 生成器函数,每一次函数调用都会得到全新的生成器对象。只要有yield语句的函数都是生成器函数
      • 生成器函数每一次执行到yield这一句,把yield的值返回
      • return非常强势,见到它函数就完了。如果你用next驱动生成器对象,碰到了return,
      • 用for不会抛出异常碰到return就退出了

惰性本身是推荐的,还有它用在了协程中,线程、进程之后

python 复制代码
# 示例
def inc():
    count = 0
    while True:
        count += 1
        return count
    
# 不会形成死循环,因为有return
python 复制代码
inc
    
# inc函数名称
# 返回结果:<function __main__.inc()>
python 复制代码
inc()
    
# 调用inc函数返回结果
# 返回结果:1
python 复制代码
def inc():
    count = 0
    while True:
        count += 1
        yield count
    
# 创建一个生成器函数
python 复制代码
inc
    
# 查看函数名称
# 返回结果:<function __main__.inc()>
python 复制代码
inc()
    
# 直接调用函数返回生成器地址
# 返回结果:<generator object inc at 0x1082e9b40>
python 复制代码
def inc():
    for i in range(5):
        yield i + 1
    
# 创建生成器函数range(5)
python 复制代码
inc, inc()

# 查看inc,调用inc返回一个生成器函数
# 返回结果:(<function __main__.inc()>, <generator object inc at 0x106164040>)
python 复制代码
print(1, next(inc()))
print(2, next(inc()))

# print next inc函数,每次都会生成一个全新的函数,所以2次执行得到的结果都是1
# 返回结果:1 1
# 返回结果:2 1
python 复制代码
g = inc()
print(next(g))
print(next(g))
print('----------')
for x in g:
    print(x)
print('==========')
print(next(g))

# 创建g变量,值是inc()函数,对变量进行next迭代的就是同一个函数,迭代器使用完之后,在使用next会抛出StopIteration(停止迭代)异常
python 复制代码
g = inc()
print(next(g))
print(next(g))
print('----------')
for x in g:
    print(x)
print('==========')
print(next(g))

# 创建g变量,值是inc()函数,对变量进行next迭代的就是同一个函数,迭代器使用完之后,在使用next会抛出StopIteration(停止迭代)异常





无限容器

python 复制代码
def foo():     
    count = 0
    while True:
        count += 1
        yield count

# 可以做id生成器
python 复制代码
x = foo()
print(1, next(x))
print(2, next(x))
print(3, next(x))

# 生成器对象是惰性对象,你要一个我给你一个,上面的例子是无线容器,容量是无限的
# 返回结果:1 1
# 返回结果:2 2
# 返回结果:3 3

计数器

python 复制代码
def inc():
    def foo():
        count = 0
        while True:
            count += 1
            yield count 
            
    c = foo() # 生成器对象
    return c

x = inc() # x的值是inc函数的调用
print(next(x))
print(next(x))
print(next(x))

# 返回结果:1
# 返回结果:2
# 返回结果:3
python 复制代码
def inc():
    def foo(): 
        count = 0
        while True:
            count += 1
            yield count
            
    c = foo() # 生成器对象
    def fn():
        return next(c)
    return fn

x = inc()
print(x)
print(x())
print(x())
print(x())

# 返回结果:<function inc.<locals>.fn at 0x1085ee8e0>
# 返回结果:1
# 返回结果:2
# 返回结果:3
python 复制代码
def inc():
    def foo(): 
        count = 0
        while True:
            count += 1
            yield count
            
    c = foo() # 生成器对象
    return lambda : next(c) # lambda方式, 闭包是c

x = inc()
print(x)
print(x())
print(x())
print(x())

# 返回结果:<function inc.<locals>.<lambda> at 0x1085edc60>
# 返回结果:1
# 返回结果:2
# 返回结果:3

生成器写斐波那契数列

python 复制代码
# fib1:1 fib2:1 fib3:2

# 定义一个生成器函数fib,用于计算斐波那契数列
def fib():
    a = 1	# 初始化第一个斐波那契数a为1
    yield a	# 使用yield关键字返回第一个斐波那契数a
    b = 1	# 初始化第二个斐波那契数b为1
    yield b	# 使用yield关键字返回第二个斐波那契数b
    while True:	# 当循环条件满足时,执行循环体
        a, b = b, a + b	# 更新斐波那契数列的下一个值
        yield b	# 使用yield关键字返回新的斐波那契数
        
f = fib() # 生成器	# 创建一个生成器对象f,用于调用fib函数
for i in range(6):	# 使用for循环遍历0到5的整数序列
    print(i+1, next(f))	# 打印当前整数i加1和对应的斐波那契数

# 返回结果:1 1
# 返回结果:2 1
# 返回结果:3 2
# 返回结果:4 3
# 返回结果:5 5
# 返回结果:6 8
相关推荐
Null箘9 分钟前
从零创建一个 Django 项目
后端·python·django
云空13 分钟前
《解锁 Python 数据挖掘的奥秘》
开发语言·python·数据挖掘
玖年1 小时前
Python re模块 用法详解 学习py正则表达式看这一篇就够了 超详细
python
岑梓铭1 小时前
(CentOs系统虚拟机)Standalone模式下安装部署“基于Python编写”的Spark框架
linux·python·spark·centos
游客5201 小时前
opencv中的各种滤波器简介
图像处理·人工智能·python·opencv·计算机视觉
Eric.Lee20211 小时前
moviepy将图片序列制作成视频并加载字幕 - python 实现
开发语言·python·音视频·moviepy·字幕视频合成·图像制作为视频
Dontla1 小时前
vscode怎么设置anaconda python解释器(anaconda解释器、vscode解释器)
ide·vscode·python
qq_529025292 小时前
Torch.gather
python·深度学习·机器学习
数据小爬虫@2 小时前
如何高效利用Python爬虫按关键字搜索苏宁商品
开发语言·爬虫·python
Cachel wood2 小时前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架