当前位置:   article > 正文

Self-study Python Fish-C Note13 P48to49

Self-study Python Fish-C Note13 P48to49

函数 (part 3)

本节主要讲函数的 lambda 表达式, 生成器

lambda 表达式 (匿名函数)(P48)

匿名函数(lambda 表达式)语法规则:lambda arg1, arg2, arg3, ... argN : expression
其中 arg 为参数,expression 为函数实现的表达式以及返回值
我们把lambda表达式作为极致精简的函数,相当于传统函数定义的:
def <lambda> (arg1,arg2,arg3,... argN): return expression
示例 1:

# 传统定义的函数
def squareX(x):
    return x*x
squareX(3)
  • 1
  • 2
  • 3
  • 4
9
  • 1
# lambda 表达式
squareY = lambda y : y*y
squareY(3)
  • 1
  • 2
  • 3
9
  • 1
# 传统定义的函数函数名就是一个函数的引用
squareX
  • 1
  • 2
<function __main__.squareX(x)>
  • 1
# 而 lambda 表达式,整个表达式就是一个函数的引用
squareY
  • 1
  • 2
<function __main__.<lambda>(y)>
  • 1

两者重大的区别就是,lambda 是一个表达式,可以用在常规函数不可能存在的地方。
示例2:lambda 表达放入列表(这里只是做示例示范可以,但不推荐大家开发的时候这么写哈)

y = [lambda x:x*x,2,3]
y[0](y[1]) # 把 y 列表的第二个值(2),传入列表第一个值 lambda 表达式中
  • 1
  • 2
4
  • 1

lambda 表达式与 mapfilter 等函数合用。这两者的参数都是要求传入一个用于计算的函数,此时就可以使用 lambda 表达式。
比如 map 函数,第一个参数就是传入一个函数的引用,第二个参数要求是序列类型,其会把每个元素挨个传递给第一个参数指定的函数,在运算之后把结果构成一个迭代器返回。
示例3:

mapped = map(lambda x:ord(x)+10, 'abcdef')
list(mapped)
  • 1
  • 2
[107, 108, 109, 110, 111, 112]
  • 1
# 如果我们用传统的函数
def tradation(x):
    return ord(x)+10
list(map(tradation,'abcdef'))
  • 1
  • 2
  • 3
  • 4
[107, 108, 109, 110, 111, 112]
  • 1
# 再比如我们用在 filter 上
list(filter(lambda x : x%2,range(10))) # 求 10 以内的所有奇数
  • 1
  • 2
[1, 3, 5, 7, 9]
  • 1

总结,lambda 是一个表达式而非语句,所以它能够出现在 Python 语法不允许 def 语句出现的地方(优势)。但由于所有的功能代码都局限在一个表达式中实现,因此 lambda 通常也只能实现那些较为简单的需求。一般来讲,匿名函数用于实现简单的需求,def 语句负责用于定义功能复杂的函数,去处理复杂的工作。

生成器 (generator) (P49)

对于调用一个普通的 Python 函数来说,一般我们都是从函数的第一行代码开始执行的,当所有语句执行完毕,或者遇到 return 语句的时候,这个函数就算是结束了。一旦函数将控制权交还给调用者的时候,这就意味这这个函数的结束。函数中做的所有工作,以及保存在局部变量中的数据也都会丢失。当再次调用的时候,一切从头开始。
有没有办法让函数在退出之后还能保留状态呢?使用闭包或者全局变量。不过过多使用全局变量会污染命名空间,闭包的定义又相对复杂。
此时,生成器 (generator) 就是一个更简单和安全的方法。
定义一个生成器:

在函数中使用 yield 表达式来代替 return语句

示例1:

def counter():
    i=0
    while i <= 3:
        yield i
        i+=1
# 这样我们就定义了一个 叫 counter 的生成器
# 现在我们调用 counter() 函数
counter() # 可以看到得到的不再是一个返回值,而是一个生成器对象 `generator object`
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
<generator object counter at 0x0000017F4A3B8430>
  • 1
# counter 现在是一个生成器了,我们可以在 for 中使用
for i in counter():
    print(i)
  • 1
  • 2
  • 3
0
1
2
3
  • 1
  • 2
  • 3
  • 4

我们知道 for 语句,是从一个可迭代对象里面每次获取一个数据。这个 counter 生成器的作用就是每次调用的时候提供一个数据,注意是提供一个数据。
更深入讲,每次在执行到 yield i的时候,就生成一个数据,暂停并保留状态。下一次调用则从下一个语句 i+=1开始继续执行。
注意:生成器它不像是列表,元组之类的可迭代对象,生成器可以看作是一个制作机器,他的作用就是每调用一次提供一个数据,并且会记住当时的状态。而列表元组这些可迭代对象则是容器,他们里面存放的是早已经准备好的所有数据。生成器是一种特殊的迭代器,他首先不走回头路,其次支持 next()函数

c = counter()
next(c)
  • 1
  • 2
0
  • 1
next(c)
  • 1
1
  • 1
next(c)
  • 1
2
  • 1
next(c)
# 如果再 使用 next(c) 就会抛出 StopIteration 的异常
  • 1
  • 2
3
  • 1

由于生成器每调用一次获取一个结果的特性,所以生成器对象是无法使用下标索引这种随机访问的方式的

c = counter()
print(next(c))
print(next(c)) # 此时 c 的状态 i =1
print('_'*30)
for i in c: # 再调用是从 i=1开始 i=i+1
    print(i)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
0
1
______________________________
2
3
  • 1
  • 2
  • 3
  • 4
  • 5

示例2:
使用生成器来实现 斐波那契数列
斐波那契数列:由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出:0,1,1,2,3,5,8 …

def fib():
    back1,back2 = 0,1
    while True:
        yield back1
        back1,back2 = back2,back1+back2
        
f = fib()
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
0
1
1
2
3
5
8
13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这里我们写了一个无限的斐波那契数列,如果我们不小心用到了 for 上,他就会一直生成下去。此时要用 control+C 强制退出,否则会一直进行下去

生成器表达式 (generator expression)

在之前的课程中我们提到过,列表有列表推导是而元组则没有。这里就可以做一个解答,列表推导式的 [] 换成 (),其实就变成了生成器表达式。
示例:

(i**2 for i in range(3))
  • 1
<generator object <genexpr> at 0x0000017F4A3C49E0>
  • 1
t = (i**2 for i in range(3)) # range(3) 包括 0,1,2 不包括 3
print(next(t))
print(next(t))
print(next(t))
  • 1
  • 2
  • 3
  • 4
0
1
4
  • 1
  • 2
  • 3

这种利用推导的形式获得生成器的方法,我们称之为生成器表达式。生成器表达式和列表推导式最大的不同就是,列表推导式会一下子将所有数据生产出来并放到一个列表中,但是生成器表达式一次只生成一个数据。
总结来说,生成生成器的两种方法一个就是使用 yield 表达式,另一个就是直接使用生成器表达式。




附言: 题目:Self-study Python Fish-C Note-13 P48-P49 本文为自学B站上鱼C的python课程随手做的笔记。一些概念和例子我个人为更好的理解做了些查询和补充 因本人水平有限,如有任何问题,欢迎大家批评指正! 原视频链接:https://www.bilibili.com/video/BV1c4411e77t?p=8

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/902788
推荐阅读
相关标签
  

闽ICP备14008679号