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
查找素数-埃氏筛法

 

posted @ 2019-06-30 22:32  甜麦地  阅读(113)  评论(0)    收藏  举报