python基础-函数
函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”:
1 a = abs 2 a(-1) # 1
坑:默认参数是可变类型
def add_end(L=[]): L.append('END') return L >>> add_end() ['END'] >>> add_end() ['END', 'END'] >>> add_end() ['END', 'END', 'END'
解释:
Python函数在定义的时候,默认参数L的值就被计算出来了,即 [],因为默认参数L也是一个变量,它指向对象 [],因为每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是参数定义的 [] 了。
定义默认参数要牢记一点:默认参数必须指向不变对象!
如果要实现上述函数功能,可以这样:
1 def add_end(L=None): 2 if L is None: 3 L = [] 4 L.append('END') 5 return L
为什么要设计str,None这样的不变对象呢?
因为不变对象一旦创建,对象内部的数据就不能修改,这样修改,这样就减少了由于修改数据的导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读不会出现问题。
递归函数
1 def fact(n): 2 if n==1: 3 return 1 4 return n * fact(n - 1)
1 def fact(n): 2 return fact_iter(n, 1) 3 4 def fact_iter(num, product): 5 if num == 1: 6 return product 7 return fact_iter(num - 1, num * product) 8 9 “”“ 10 return fact_iter(num - 1, num * product) 仅返回函数本身,num-1 和num*product在函数调用前就会被计算,不影响函数调用。 11 ”“”
但是!python标准解释器没有对尾递归做优化,任何递归函数都存在栈溢出的问题。
迭代器
for循环的工作原理 1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic 2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码 3: 重复过程2,直到捕捉到异常StopIteration,结束循环
#优点:
- 提供一种统一的、不依赖于索引的迭代方式 - 惰性计算,节省内存,可以表示一个无限大的数据流
#缺点: - 无法获取长度(只有在next完毕才知道到底有几个值) - 一次性的,只能往后走,不能往前退
迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象
高阶函数
map 和 filter 函数返回的都是一个Iterator,也就是一个惰性序列。
1 def _odd_iter(): 2 n = 1 3 while True: 4 n = n + 2 5 yield n 6 7 8 def _not_divisible(n): 9 return lambda x: x % n > 0 10 11 12 def primes(): 13 yield 2 14 it = _odd_iter() # 初始序列 15 while True: 16 n = next(it) # 返回序列的第一个数 17 yield n 18 it = filter(_not_divisible(n), it) # 构造新数列 19 20 21 for n in primes(): 22 if n < 50: 23 print(n) 24 else: 25 break

浙公网安备 33010602011771号