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
相关推荐
databook6 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar8 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户8356290780518 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_8 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
数据智能老司机15 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机16 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机16 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机16 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i16 小时前
drf初步梳理
python·django
每日AI新事件16 小时前
python的异步函数
python