Python基础10-函数的递归

2022-09-26 11:44:52 浏览数 (1)

  • 函数递归介绍
  • 三元表达式
  • 列表生成式字典生成式集合生成式
  • 匿名函数

-曾老湿, 江湖人称曾老大。


-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。


函数递归介绍


什么是函数递归

函数嵌套调用的一种特殊形式,在调用一个函数的过程中,又直接或间接的调用该函数本身,称之为函数的递归调用

例如:

代码语言:javascript复制
def foo():
    print('from foo')
    foo()

foo()

函数调用深度

代码语言:javascript复制
def foo(n):
    print('from foo',n)
    foo(n 1)

foo(0)

代码语言:javascript复制
def bar():
    print('from bar')
    foo()
    
def foo():
    print('from foo')
    bar()

foo()

以上的这两种,都没有啥意义,调用完,报错...

代码语言:javascript复制
递归调用必须有两个明确的阶段
1.回溯:一次次递归调用下去,但是需要注意的是,每一次重复,问题的规模都应该有所减少,直到最小值,即回溯阶段要有一个明确的结束条件.
2.递推:往回一层一层的推算出结果

def age(n):
    if n == 1:
        return 18
    return age(n-1)   2
print(age(5))

为啥要用递归?

举个栗子:

有一个列表 l=[1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,]]]]]]]]]]]

想取出里面的数据

代码语言:javascript复制
l=[1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,]]]]]]]]]]]

for item in l:
    if type(item) is not list:
        print(item)
    else:
        for i in item:
                if type(i) is not list:
                    print(i)
                else:
                    for n in i:
                        print(n)

代码还没写完,无限循环下去吧...

此时此刻,用递归函数就会好很多,递归只需要把控好结束条件,代码如下,它不香嘛?

代码语言:javascript复制
l=[1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,]]]]]]]]]]]
def search(l):
    for item in l:
        if type(item) is not list:
            print(item)
        else:
            search(item)

search(l)


函数递归调用应用于算法

现在有一个列表,里面有很多个数字,从小到排列,现有需求找到某一个数字 nums=[13,15,17,23,31,53,74,81,93,102,201,303,403,503,777]

代码语言:javascript复制
# 需求一:找到15
nums=[13,15,17,23,31,53,74,81,93,102,201,303,403,503,777]
find_num=15
for num in nums:
    if num == find_num:
        print('find it:',num)
        break

## emm...运气好 ,15就在第二个,两次就找到了
## 如果找503呢?
## 如果这个数字列表有一万个字呢?
## 效率是不是很低?

# 需求二:提高效率(二分法)
def binary_search(nums,find_num):
    print(nums)
    mid_index=len(nums) // 2
    if find_num > nums[mid_index]:
        # in the right
        nums=nums[mid_index 1:]
        binary_search(nums,find_num)
    elif find_num < nums[mid_index]:
        # in the left
        nums=nums[0:mid_index]
        binary_search(nums, find_num)
    else:
        print('find it',nums[mid_index])


binary_search(nums,find_num)

用了4次就可以找到

三元表达式


作用

会:可以让自己的代码变的更简洁 不会:也没有太大影响...


举例

代码语言:javascript复制
# 以前我们写过一个函数,比较两个数的大小
def max2(x,y):
    if x > y:
        return x
    else:
        return y

print(max2(1,10))

# 三元表达式实现
def max2(x,y):
   return x if x > y else y
print(max2(1,10))


# 再举个例子
name=input('your name: ').strip()
res="SB" if name == "haifeng" else "NB"
print(res)

列表生成式字典生成式集合生成式


列表生成式

代码语言:javascript复制
# 语法
[expression for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN
]
类似于
res=[]
for item1 in iterable1:
    if condition1:
        for item2 in iterable2:
            if condition2
                ...
                for itemN in iterableN:
                    if conditionN:
                        res.append(expression)

# 优点:方便,改变了编程习惯,可称之为声明式编程

举例

现有一个名字的列表 names=['qls','lls','zhang3','li4','wang5']

代码语言:javascript复制
# 需求一:将名字后面都加上一个"大帅比"的后缀
names=['qls','lls','zhang3','li4','wang5']
l=[]
for name in names:
    res=name   '_DSB'
    l.append(res)

print(l)

## 罗里吧嗦,很麻烦
# 使用列表生成式,一行代码搞定
names=['qls','lls','zhang3','li4','wang5']
l=[name   'DSB' for name in names]
print(l)


# 需求二:将列表中,zls这个名字排除在外
names=['qls_sb','lls_sb','zhang3_sb','li4_sb','wang5_sb','zls']
l=[]
for name in names:
    if name.endswith('sb'):
        l.append(name)
print(l)

# 列表生成式,加判断
l=[name for name in names if name.endswith('sb')]
print(l)

字典生成式

现有两个列表 keys=['name','age','gender'] values=['zls',18,'male']

代码语言:javascript复制
# 补充技巧 ,python内置enumerate()方法
l=['a','b','c','d']
for item in enumerate(l):
    print(item)

代码语言:javascript复制
# 那么我们变量解压
l=['a','b','c','d']
for i,v in enumerate(l):
    print(i,v)

代码语言:javascript复制
# 需求一:把这两个列表,合并成一个字典
keys=['name','age','gender']
values=['zls',18,'male']
dic={}
for i,k in enumerate(keys):
    dic[k] = values[i]

print(dic)

# 需求二:字典生成式,一行代码搞定
keys=['name','age','gender']
values=['zls',18,'male']
dic={k:values[i] for i,k in enumerate(keys)}
print(dic)

# 需求三:字典生成式,加判断
keys=['name','age','gender']
values=['zls',18,'male']
dic={k:values[i] for i,k in enumerate(keys) if i > 0}
print(dic)

集合生成式

代码语言:javascript复制
# 和字典生成式比较
## 字典
print({i:i for i in range(10)})

## 集合
print({i for i in range(10)})

但是,集合有两个特性: 1.去重 2.无序

代码语言:javascript复制
# 例如
print({i for i in 'hello'})

# 结果

匿名函数


什么是匿名函数?

匿名:就是没有名字 匿名函数:没有名字的函数

以前我们在定义函数的时候,为啥有名字呢?因为我们要保存下来,需要开辟一块内存空间,那么为什么要用匿名函数呢?作用就是,为了这个函数我们只使用一次的时候,不需要占用内存,没有重复使用的需求。


举例

代码语言:javascript复制
# 写一个求和的函数
def sum2(x,y):
    return x y

print(sum2(1,5))

# 匿名函数
lambda x,y:x y

# 打印出来,会发现是一个内存地址,如此一来,我们加上括号就可以调用
print(lambda x,y:x y)

# 错误写法
print(lambda x,y:x y(1,2))

## 打印出来,还是内存地址,为啥呢... 因为是y(1,2),所以我们需要,把整个函数括起来

# 正确写法
print((lambda x,y:x y)(1,2))


匿名函数配合其他函数使用

内置函数:max,min,sorted,map,filter,reduce 自定义函数:xxx

代码语言:javascript复制
# 现有一薪资列表
salaries={
    'zls':10000000,
    'qls':10000,
    'lls':11111,
    'zhang3':100,
    'li4':1
}

# 需求一:max 求出薪资最高的人名:即比较的是字典的value,但是取的结果是key
salaries={
    'zls':10000000,
    'qls':10000,
    'lls':11111,
    'zhang3':100,
    'li4':1
}

def func(name):
    return salaries[name]
res=max(salaries,key=func)
print(res)

# 使用匿名函数
salaries={
    'zls':10000000,
    'qls':10000,
    'lls':11111,
    'zhang3':100,
    'li4':1
}

res=max(salaries,key=lambda name:salaries[name])
print(res)

## 需求二:min 求最小薪资
salaries={
    'zls':10000000,
    'qls':10000,
    'lls':11111,
    'zhang3':100,
    'li4':1
}

res=min(salaries,key=lambda name:salaries[name])
print(res)

# 需求三:使用 sorted 排序,按照薪资从小到大排序(从大到小 reverse=True 即可)
salaries={
    'zls':10000000,
    'qls':10000,
    'lls':11111,
    'zhang3':100,
    'li4':1
}
res=sorted(salaries,key=lambda name:salaries[name])
print(res)

res=sorted(salaries,key=lambda name:salaries[name],reverse=True)
print(res)

# 需求四:使用 map 映射,把每一个人名加上DSB
names=['lxx','qxx','zhang3','li4']
res=map(lambda name:name   'DSB',names)
print(list(res))

# 需求五:filter 把所有以sb结尾的换成DSB
names=['lxx_sb','qxx_sb','zhang3_sb','zls','li4_sb']
res=filter(lambda name:name.endswith('sb'),names)
print(list(res))

# 需求六:reduce,把多个值合并成一个结果
from functools import reduce
l=['a','b','c','d']
res=reduce(lambda x,y:x y,l,'A')
print(res)


# 需求七:reduce,1-100相加
from functools import reduce
res=reduce(lambda x,y:x y,range(1,101))
print(res)

0 人点赞