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
相关推荐
斯凯利.瑞恩1 分钟前
Python决策树、随机森林、朴素贝叶斯、KNN(K-最近邻居)分类分析银行拉新活动挖掘潜在贷款客户附数据代码
python·决策树·随机森林
yannan2019031322 分钟前
【算法】(Python)动态规划
python·算法·动态规划
蒙娜丽宁32 分钟前
《Python OpenCV从菜鸟到高手》——零基础进阶,开启图像处理与计算机视觉的大门!
python·opencv·计算机视觉
光芒再现dev34 分钟前
已解决,部署GPTSoVITS报错‘AsyncRequest‘ object has no attribute ‘_json_response_data‘
运维·python·gpt·语言模型·自然语言处理
好喜欢吃红柚子1 小时前
万字长文解读空间、通道注意力机制机制和超详细代码逐行分析(SE,CBAM,SGE,CA,ECA,TA)
人工智能·pytorch·python·计算机视觉·cnn
小馒头学python1 小时前
机器学习是什么?AIGC又是什么?机器学习与AIGC未来科技的双引擎
人工智能·python·机器学习
神奇夜光杯1 小时前
Python酷库之旅-第三方库Pandas(202)
开发语言·人工智能·python·excel·pandas·标准库及第三方库·学习与成长
千天夜1 小时前
使用UDP协议传输视频流!(分片、缓存)
python·网络协议·udp·视频流
测试界的酸菜鱼1 小时前
Python 大数据展示屏实例
大数据·开发语言·python
羊小猪~~1 小时前
神经网络基础--什么是正向传播??什么是方向传播??
人工智能·pytorch·python·深度学习·神经网络·算法·机器学习