小甲鱼Python学习笔记之函数(二)

lambda表达式

lambda表达式也称为匿名函数,能够使用一行代码实现比较复杂函数功能,使代码更加简洁。

语法规则

在这里插入图片描述

与传统函数的区别:

传统定义方式定义的函数,函数名是一个函数的引用

>>> def square(x):
	return x*x

>>> square(3)
9
>>> square
<function square at 0x0000021CAB808B80>

而lambda表达式整个表达式是一个函数的引用

>>> squareY=lambda y:y*y
>>> squareY(3)
9
>>> squareY
<function <lambda> at 0x0000021CAB808C10>

好处

lambda是一个表达,它可以用在常规函数不可以使用的地方,比如:

  • 把lambda放在列表中,
>>> y=[lambda x:x*x,2,3]
>>> y[0]   //y[0]是一个函数的引用,调用这个函数时需要加小括号,并将参数放在小括号中
<function <lambda> at 0x0000021CAB808CA0>
>>> y[0](y[1])  //将列表中的第二个元素作为参数传入lambda表达式中,得到平方返回
4
>>> y[0](y[2])
9
  • 把lambda表达式用在map函数中
>>> mapped=map(lambda x:ord(x)+10,"FishC")     //使用lambda表达式实现
>>> list(mapped)
[80, 115, 125, 114, 77]
>>> def boring(x):           //使用传统定义函数的方式将字符型转化为整型
	return ord(x)+10

>>> list(map(boring,"FishC"))
[80, 115, 125, 114, 77]

map函数有两个参数,第一个参数要求传入一个用于计算的函数,是引用,第二个参数是序列类型,该函数的功能是把序列(第二个参数)中每个元素逐个传递给第一个参数指定的函数,在运算之后把他们的结果构成一个迭代器。

  • 把lambda表达式用在filter函数中
>>> list(filter(lambda x:x%2,range(10)))
[1, 3, 5, 7, 9]

总结
lambda是一个表达式而非语句,因此可以使用lambda做简单的事情,用def语句去定义功能复杂的函数。

迭代器

定义

  Python中一个实现了_iter_方法和_next_方法的类对象,就是迭代器.
  对于list、string、tuple、dict等这些容器对象,使用for循环遍历是很方便的。在后台for语句对容器对象调用iter()函数。==iter()是python内置函数。iter()函数会返回一个定义了next()方法的迭代器对象,它在容器中逐个访问容器内的元素。next()也是python内置函数。在没有后续元素时,next()会抛出一个 StopIteration ==异常,通知for语句循环结束。

  迭代器可以用来帮助我们记录每次迭代访问到的位置,当我们对迭代器使用next()函数的时候(调用了迭代器对象的_next_方法),迭代器会向我们返回它所记录位置的下一个位置的数据。

迭代器协议

对象需要提供next()方法,它要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代。

可迭代对象

  实现了迭代器协议的对象。list、tuple、dict都是Iterable(可迭代对象),但不是Iterator(迭代器对象)。但可以使用内置函数iter(),把这些都变成Iterable(可迭代器对象)。
  for item in Iterable 循环的本质就是先通过iter()函数获取可迭代对象Iterable的迭代器,然后对获取到的迭代器不断调用next()方法来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环结束
在这里插入图片描述

用迭代器实现斐波那契数列

>>> class Fibs:
	def __init__(self):
		self.a=0
		self.b=1
	def __iter__(self):     //__iter__()返回迭代器本身
		return self
	def __next__(self):     //__next__()制定迭代器的规则
		self.a,self.b=self.b,self.a + self.b
		return self.a

	
>>> fibs=Fibs()
>>> for each in fibs:
	print(each)

	
1
1
2
3
5
8
13
21
34
55
89
144
233
377

生成器

Q:函数调用结束之后,一切都要从头再来,那么有没有办法让函数再退出之后还能保留状态呢?
A:①闭包(外层函数结束调用之后内层函数还是可以记住外层函数的参数)②生成器
Q:Python生成器是模仿协同程序实现的吗?
A:是的,协同程序是可以运行的独立函数调用,函数可以暂停或挂起,并在需要的时候从程序离开的地方继续或者重新开始。

定义

生成器使用yield语句来代替函数中的return语句,yield语句挂起该生成器函数的状态,保留足够的信息,以便之后从它离开的地方继续执行。

使用

Q:如何使用生成器呢?

>>> def counter():
	i=0
	while i <= 5:
		yield i      //每次执行到yield语句时,就生成一个数据暂停并保留状态

		i += 1      // 下一次调用从此处开始执行

		
>>> counter()
<generator object counter at 0x0000021CAB7DDF20>
>>> for i in counter():
	print(i)

	
0
1
2
3
4
5

for语句的功能是从一个可迭代对象中每次获取一个数据;counter生成器的作用是每次调用的时候提供一个数据
Note:

  • 生成器不像列表,元组这些可迭代对象,生成器是一个制作机器,作用是每调用一次提供一个数据,并且记住当时的状态,而列表,元组这些可迭代对象是容器,里面存放的是早已经生成好的所有数据
  • 生成器是特殊的迭代器,支持next()函数,但是next函数不支持下标索引的方式。(因为并没有提前生成好)
>>> c=counter()
>>> c
<generator object counter at 0x0000021CAB81DBA0>
>>> next(c)
0
>>> next(c)
1
>>> next(c)
2

>>> next(c)
3
>>> next(c)
4
>>> next(c)
5
>>> next(c)   //调用结束后,会抛出StopIteration异常
Traceback (most recent call last):
  File "<pyshell#69>", line 1, in <module>
    next(c)
StopIteration

用生成器实现斐波那契数列

# 菲波那切数列
def Fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return '亲!没有数据了...'
# 调用方法,生成出10个数来
f=Fib(10)
# 使用一个循环捕获最后return 返回的值,保存在异常StopIteration的value中
while  True:
    try:
        x=next(f)
        print("f:",x)
    except StopIteration as e:
        print("生成器最后的返回值是:",e.value)
        break
>>> def fibs():
	a=0
	b=1
	while True:
		a,b=b,a+b
		yield a

		
>>> for i in fibs():
	if each > 100:     //如果没有设置退出条件的话,会产生“无穷无尽项”,使用Ctrl+c停止
		break
	else:
		print(each)

1
1
2
3
5
8
13
21
34
55
89		

用闭包实现斐波那契数列
待更新…

生成器表达式

利用推导的形式获得生成器的方法,称为生成器表达式法:

>>> (i ** 2 for i in range(10))
<generator object <genexpr> at 0x0000021CAB81DC80>
>>> t=(i ** 2 for i in range(10))
>>> next(t)       //每次产生一个数据
0
>>> for i in t:
	print(i)

	
1
4
9
16
25
36
49
64
81

列表推导式(用方括号表示[]):

>>> a=[i for i in range(100) if not(i%2) and i%3]
>>> a
[2, 4, 8, 10, 14, 16, 20, 22, 26, 28, 32, 34, 38, 40, 44, 46, 50, 52, 56, 58, 62, 64, 68, 70, 74, 76, 80, 82, 86, 88, 92, 94, 98]

字典推导式(键值对):

>>> b={i:i%2==0 for i in range(10)}
>>> b
{0: True, 1: False, 2: True, 3: False, 4: True, 5: False, 6: True, 7: False, 8: True, 9: False}

集合推导式(用{ }表示):

>>> c={i for i in [1,2,1,4,2,5,6,3,7,3]}
>>> c
{1, 2, 3, 4, 5, 6, 7}

元组推导式用圆括号表示(),就是生成器表达式

>>> e=(i for i in range(10))
>>> e
<generator object <genexpr> at 0x0000021CAB81DBA0>
>>> next(e)
0
>>> next(e)
1
>>> next(e)
2
>>> next(e)
3
>>> next(e)
4
>>> next(e)
5
>>> next(e)
6
>>> next(e)
7
>>> next(e)
8
>>> next(e)
9
>>> next(e)
Traceback (most recent call last):
  File "<pyshell#198>", line 1, in <module>
    next(e)
StopIteration
>>> sum(i for i in range(100) if i % 2)
2500

总结
实现生成器的两种方式:

  1. 将普通函数中的return替换成yield
  2. 使用生成器表达式

参考:Python中生成器和迭代器的区别.
   深入剖析可迭代对象和迭代器的区别和联系.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值