函数
匿名函数
匿名函数就是不需要指定函数的名字,比如lambda x: x * x
。相当与:
1 | # ':'前的x为函数参数,后面的为返回值 |
函数参数
可变参数:可以接受所有参数
1 | def calc(*numbers): |
关键字参数:使用**
来定义,允许传入0个或者任意个含参数名的参数,在内部自动组装成dict
1 | def person(name, age, **kw): |
命名关键字参数:可以限制关键字参数的名字,比如只接受某个参数名为关键字参数。命名关键字参数需要用*
进行分隔开,*
后面的参数被视为关键字参数。
1 | # 只接收city和job作为关键字参数。 |
递归函数:
在函数内部,可以调用其他函数,如果一个函数在内部调用自身,那么就称作递归函数。
1 | def fact(n): |
递归函数的优点:逻辑清晰,但是使用尾递归要注意防止栈溢出。(函数是通过栈这种数据结构来实现的。所以递归调用的次数越多,会导致栈溢出) 解决这个办法是通过尾递归优化。
尾递归优化
:当函数返回的时候,调用自身本身,并且return语句不能包含表达式。这样编译器或者就是去就可以把尾递归做优化,使得尾递归不论本身调用多少次,都只占用了一个栈。不会出现栈溢出的情况。上面的例子return n * fact(n - 1)不是一个尾递归。
一个尾递归的例子:
1 | # 这个函数是一个递归调用,所以并不会导致栈溢出。但是由于Python解释器并没有做尾递归优化,所以仍然会导致栈溢出。 |
列表生成式:
如果想要生成一个list,可以使用list(range(1, 11))
,也可使用for循环,然而使用列表生成式
可以很方便的生成list:把要生成的元素x * x
放到前面,后面跟着for循环,就可以把list创建出来
1 | [x * x for x in range(1, 11)] |
后面还可以跟if
语句,求偶数的平方:
1 | for x in range(1, 11) if x % 2 == 0] [x * x |
使用两层循环,使用两个变量来生成list:
1 | for m in 'ABC' for n in 'XYZ'] [m + n |
生成器与迭代器
生成器:
Python中,一边循环一边计算的机制,称为生成器(generator),只要把一个列表生成式的[]
改成()
,就创建了generator。
有两种方式创建生成器:
1 | # 列表生成式 |
第二种方法创建生成器,如果函数定义中包含yield
关键字,那么这个函数就是一个生成器。在generator
当中,每次调用next()
的时候执行,遇到yield
语句返回,再次执行时从上次返回的yield
语句处继续执行,举个简单的例子:
1 | def odd(): |
在使用for循环调用generator
时,如果想要拿到返回值,必须捕获错误,返回值包含在StopIteration
的value
中:
1 | 6) g = fib( |
###迭代器:
Python 中可以直接作用于for循环的对象统称为可迭代对象:Iterable
。使用 isinstance()
判断一个对象是否是可迭代对象Iterable
1 | from collections import Iterable |
生成器不但可以作用于 for 循环,而且可以被 next() 函数不断调用返回下一个值,直到最后抛出StopIteration错误,这样可以被next()函数不断返回下一个值得对象称为迭代器:Iterator
。
生成器都是Iterator
对象,但是list
、dict
、str
是可迭代对象(Iterable
),但是不是迭代器Iterator
。需要把以上类型变成可迭代对象可以使用 iter()
函数。
1 | isinstance(iter([]), Iterator) |
list
、dict
、str
等数据不是Iterator
的原因是:Python 中的Iterator
对象表示的是一个数据流,Iterator
对象可以被next()
函数不断调用返回下一个数据,直到没有数据时抛出StopIterator
错误。可以把这个数据流看做是一个有序的序列,但我们却不能提前直到这个序列的长度,只能不断的调用next()
函数事项按需计算下一个数据,所以Iterator
的计算是惰性的,只有在需要返回下一个数据的时候才会计算,Iterator
甚至可以表示出一个无限大的数据流,例如全体自然数,而使用list是完全不可能存储全体自然数的。
总结:
凡是可以作用于 for 循环的对象都是 Iterable
类型。
凡是可以作用于 next()
函数的对象都是 Iterator
类型,表示一种惰性计算。
集合数据类型如:list
、dict
、str
等是Iterable
但不是Iterator
,不过可以通过iter()
函数获取Iterator
对象。