函数递归与生成式

1、函数递归:python

1.定义:函数不只能够嵌套定义,还能够嵌套调用,即在调用一个函数的过程当中,函数内部又调用另外一个函数,而函数的递归调用指的是在调用一个函数的过程当中又直接或间接地调用该函数自己编程

在调用f1的过程当中,又调用f1,这就是直接调用函数f1自己

def
f1(): print('from f1') f1() f1()


在调用f1的过程当中,又调用f2,而在调用f2的过程当中又调用f1,这就是间接调用函数f1自己
def f1(): print('from f1') f2() def f2(): print('from f2') f1() f1()

从上图能够看出,两种状况下的递归调用都是一个无限循环的过程,但在python对函数的递归调用的深度作了限制,于是并不会像你们所想的那样进入无限循环,会抛出异常,要避免出现这种状况,就必须让递归调用在知足某个特定条件下终止。app

#1. 可使用sys.getrecursionlimit()去查看递归深度,默认值为1000,虽然可使用
sys.setrecursionlimit()去设定该值,但仍受限于主机操做系统栈大小的限制

#2. python不是一门函数式编程语言,没法对递归进行尾递归优化。

2、回溯与递推编程语言

某公司四个员工坐在一块儿,问第四我的薪水,他说比第三我的多1000,问第三我的薪水,第他说比第二我的多1000,问第二我的薪水,他说比第一我的多1000,最后第一人说本身每个月5000,请问第四我的的薪水是多少?函数式编程

思路解析:函数

要知道第四我的的月薪,就必须知道第三我的的,第三我的的又取决于第二我的的,第二我的的又取决于第一我的的,并且每个员工都比前一个多一千,数学表达式即:优化

salary(4)=salary(3)+1000 
salary(3)=salary(2)+1000 
salary(2)=salary(1)+1000 
salary(1)=5000
总结为: 
salary(n)=salary(n-1)+1000 (n>1) 
salary(1)=5000 (n=1) 

很明显这是一个递归的过程,能够将该过程分为两个阶段:回溯和递推。spa

​ 在回溯阶段,要求第n个员工的薪水,须要回溯获得(n-1)个员工的薪水,以此类推,直到获得第一个员工的薪水,此时,salary(1)已知,于是没必要再向前回溯了。而后进入递推阶段:从第一个员工的薪水能够推算出第二个员工的薪水(6000),从第二个员工的薪水能够推算出第三个员工的薪水(7000),以此类推,一直推算出第第四个员工的薪水(8000)为止,递归结束。须要注意的一点是,递归必定要有一个结束条件,这里n=1就是结束条件。操作系统

def salary(n):
    if n==1:
        return 5000
    return salary(n-1)+1000

s=salary(4)
print(s)

 

在未知足n\=\=1的条件时,一直进行递归调用,即一直回溯,见图4.3的左半部分。而在知足n\=\=1的条件时,终止递归调用,即结束回溯,从而进入递推阶段,依次推导直到获得最终的结果。code

递归本质就是在作重复的事情,因此理论上递归能够解决的问题循环也均可以解决,只不过在某些状况下,使用递归会更容易实现,好比有一个嵌套多层的列表,要求打印出全部的元素,代码实现以下

# l = [1,[2,[3,[4,[5,[6,[7,[8,[9]]]]]]]]]
#
# def foo(l):
#     for item in l:
#         if type(item) is not list:
#             print(item)
#         else:
#             foo(item)
#
#
# foo(l)

使用递归,咱们只须要分析出要重复执行的代码逻辑,而后提取进入下一次递归调用的条件或者说递归结束的条件便可,代码实现起来简洁清晰

3、生成式

# 一 列表生成式
# l = []
# for i in range(1, 6):
#     if i > 3:
#         l.append(i)
# print(l)

# l = [i for i in range(1,6)]
# l = [i**2 for i in range(1,6)]

# l = [i for i in range(1,6) if i > 3]
# print(l)

# names = ['liusir_dsb', 'housir_dsb', 'egon', 'wusir_dsb']

# res = [name for name in names if name.endswith('dsb')]
# print(res)

# 二 字典生成式
# res = {k:v for k,v in [('name', 'egon'), ('age', 18)]}
# res = {i:i for i in range(5)}
# print(res)

# 三 集合生成式
# res = {i for i in range(5)}
# print(res,type(res))

# 四 生成器表达式
# l = [i for i in range(1,6)]
# g = (i for i in range(1,6))
# print(g)
#
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))


with open('a.txt',mode='rt',encoding='utf-8') as f:
    # res = f.read()
    # print(len(res))

    # res = 0
    # for line in f:
    #     res += len(line)

    # res = sum([len(line) for line in f])
    # res = sum((len(line) for line in f))
    res = sum(len(line) for line in f)
    print(res)

4、匿名函数

     1.匿名函数只能用一次

 def foo(x, y):
return x + y
2.调用匿名函数的方式:
# 调用匿名函数方式一
# f=lambda x,y:x+y
# print(f(1,2))

# 调用匿名函数方式二
# res = (lambda x,y:x+y)(1,2)
# print(res)
 

3.匿名函数真正的用途是与其余函数配合使用

 

salaries = {
    'axx': 30000,
    'bxx': 3000,
    'cxx': 2000,
    'egon': 1000,
    'zxx': 500
}

# print(max([33,44,11,99]))

# def func(k):
#     return salaries[k]

# print(max(salaries,key=func))

# print(max(salaries,key=lambda k:salaries[k]))
# print(min(salaries,key=lambda k:salaries[k]))
print(sorted(salaries,key=lambda k:salaries[k]))
print(sorted(salaries,key=lambda k:salaries[k],reverse=True))