函数的递归、二分法、三元表达式、列表生成式、匿名函数

函数的递归
函数在调用阶段直接或间接的又调用自身


def func():  #在全局名称空间
    print('from func')  #函数体代码,创建一个属于函数的局部名称空间
    func()  #只要一运行这个函数体代码,就要创建一个局部名称空间,重复的创建名称空间
func()
#报错:递归错误,已经超过最大递归深度,函数体代码结束,才会运行结束,这个错是python解释器给加的错,防止内存满了溢出,提前把错误抑制住,最大递归深度

 

利用一个模块查看他的长度
import sys
print(sys.getrecursionlimit()) #获取递归的限制,数据不是很精确,997-998左右


sys.setrecursionlimit() #可以修改递归深度

函数不应该无限制的递归下去

间接
def index():
    print('from index')
    login()

def login():
    print('from login')
    index()

login()

  

递归
1.回溯:就是一次次重复的过程,但是这个重复的过程必须建立在每一次重复问题的复杂度都应该下降
直到有一个最终的结束条件
2.递推:一次次往回推导的过程

age(5) = age(4) +2
age(4) = age(3) +2
age(3) = age(2) +2
age(2) = age(1) +2
age(1) = 18

age(n) = age(n-1) + 2   #n > 1
age(1) = 18  #n = 1

'''
def age(n):
    if n == 1:  #必须要有结束条件
        return 18
    return age(n-1) +2
res = age(5)
print(res)


#递归函数类似于一个while循环  一个for循环

1 = [1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,]]]]]]]]]]]]]
将列表中的数字依次打印出来(循环的层数是你必须考虑的点)
for i in l:
    if type(i) is int:
        print(i)
    else:
        for item in i:
            if type(item) is int:
                print(item)
            else:
                for j in item:
                    if type(item)is int:
                        print(item)
                    else:
                        ...


def get_num(l):
    for i in l:
        if type (i) is int:
            print(i)
        else:
            get_num(i)
get_num(i)递归函数不需要考虑循环的次数   只需要把握结束的条件即可
算法之二分法

算法是解决问题的高效率的方法,
把算法优化,这个算法可用在程序的设计


l = [1,3,5,12,57,89,101,123,146,167,179,189,345]
num = 5
 for i in l:
     if num == i:
         print('find it')

 二分法:容器类型里面的数字必须要有大小顺序,无序的话用不了,用二分法找数字 次数降低 提高效率 每一次取列表中间的元素 先取列表的长度然后除以二,然后是中间的索引值,然后拿着索引值再跟目标数字比对一下 看看是大是小 如果比目标数字大 利用列表的切片再切出一个小列表来,然后再来比

target_num = 179
def get_num(l,target_num): #先定义一个函数,里面接收个l列表,然后再接收个数字target_num
    #获取列表中间的索引
    middle_index = len(l)// 2   #得到中间索引
    #然后对比target_num跟middle_index对比的数字的大小
    if target_num > l[middle_index]:
        #切去列表右半部分
        num_1 = l[middle_index + 1:]
        #再递归调用get_num函数
        get_num(num_1,target_num)
    elif target_num < l[middle_index]:
    #切取列表左半部分
        num_left = l[0:middle_index]
    #再递归调用get_num函数
        get_num(num_left,target_num)
    else:
        print('find it',target_num)

get_num(l,target_num)

  def index():

    pass  #第一种顶替方式
... #第二种顶替方式 推荐用pass


三元表达式
d
ef my_max(x,y):
    if x > y:
        return x
    else:
        return y
'''
当x大的时候返回x当y大的时候返回y
当某个条件成立的时候做一件事  不成立做另外一件
    '''
x = 1
y = 2
res =x if x > y else y
#如果if后面的条件成立返回if前面的值,否则返回else后面的值
print(res)
三元表达式固定表达式
值1 if条件 else 值2
条件成立 值1
条件不成立 值2

切记 不能用三元表达式套三元表达式
三元表达式的应用场景只推荐只有两种的情况下的可能 这种简单的场景

is_free = input('请输入是否免费(y/n)>>>:')
is_free = '免费' if is_free == 'y' else '收费'
print(is_free)

user = input('username>>>:')
res = 'NB' if username == 'jason' else '垃圾'
print(res)
列表生成式
l = ['tank','nick','oscar','sean']
l1 = []
for name in l:

    l1.append('%s_sb'%name)
    # l1.append(name + '_sb')  #不推荐使用  因为python里面这种字符串的拼接效率极低
print(l1)

l = ['tank_sb','nick_sb','oscar_sb','sean_sb','jason_NB']


# res = ['%s DSB'%name for name in l]
# print(res)

res = [name for name in l if name.endswith('_sb')]  #后面不支持再加else的情况
#先for循环依次取出列表里面的每一个元素
#然后交由if判断  条件成立才会交给for前面的代码
#如果条件不成立  当前的元素  直接舍弃

print(res)
字典生成式

l1 = ['name','password','hobby']
l2 = ['jason','123','DBJ']

# d = {}  #创建一个空字典
# for i,j in enumerate(l1):
#     d[j] = l2[i]
# print(d)

l1 = ['jason','123','read']
d = {i:j for i,j in enumerate(l1)}
print(d)
#跟列表生成式规律是一模一样的
#区别由中括号换成大括号了
#从原来的一个单独的变量名变成了一个i:j这种冒号形式的k,v形式的

 集合生成式

res = {i for i in range(10) if i != 4 }
print(res)   #结果是把4去除了


res1 = (i for i in range(10) if i != 4)  #这样写不是元组生成式   而是生成器表达式
# print(res1)
for i in res1:
    print(i)

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

特点:临时存在,用完就没有了

def my_sum(x,y):
    return x + y

res = (lambda x,y:x+y)(1,2)  #它本身没有名字   是个函数  函数加括号可以调用,这样写有个缺陷
                             #右键一运行就没了,下面就用不到这个函数了,只能重新写
print(res)
#:左边的相当于函数的形参
#:右边的相当于函数的返回值
#匿名函数通常不会单独使用,是配合内置函数一起使用


func = lambda x,y:x+y  #给这个函数命个名,把匿名函数变成一个有名函数
print(func()    #lambda是个关键字  定义的话前面是参数后面是返回值  单独使用没有任何意义  一般结合内置函数一起用

常用内置函数
取最大值
l = [1,2,3,4,5]
print(max(1))  #内部原理是基于for循环,依次取出每一个元素然后比大小

'''
ASCII码表
A-Z   对应的数字是65-90
a-z   对应的数字是97-122
大写字母和小写字母之前空了几个是符号的编号


'''
d = {
    'egon':30000,
    'jason':8888888,
    'nick':3000,
    'tank':1000
}
# print(max(d))  #求出的是tank,因为字典for循环只能拿到k,它对比的是首字母,ASCII码表的字母大小

 

比较薪资  返回人名
# def index (name):
#     return d[name]

print(max(d,key=lambda name:d[name]))
#第一个name是for循环拿到的key,d是字典,字典根据k取到value
#name冒号后面相当于一个返回值,返回一个数字,它会拿数字去比较


#max还支持传一个函数进来  max在比较大小的时候,
#如果不给它传一个key+函数,它的比较规则就是你给我什么我就按照大小来比较
#如果你给它字符,它就按照字符对应的ASCII码对比大小,如果给的是数字就按照给的数字大小来比较
#但是一旦你指定的key的关键字,它的规则就按key这个函数里面的规则,函数里面怎么写就怎么比

# 求最少薪资的人名
print(min(d,key=lambda name:d[name]))   #tank


map zip filter sorted reduce 这几个是比较常用和好用的内置方法
map  映射  #传一个容器类型进去可以通过函数来控制它返回的结果  基于for循环
l = [1,2,3,4,5,6]
# print(list('hello'))   #for循环hello,组织成一个列表
print(list(map(lambda x:x+1,l)))  #基于for循环   2,3,4,5,6,7  +1就是每个数字+1
#for循环第一次拿到1,1给了x,x返回的是2,会自动保存起来,第一次是2,第二次是3,依次类推




zip 拉链,它的功能强大,传多少个,都能一一对应,基于for循环
l1 = [1,2,3]
l2 = ['jason','egon','tank']
print(list(zip(l1,l2)))  #得出一个大列表  里面是一个个元组  两两组合在一起
多一个也不行  少一个也不行

 filter 过滤 基于for循环

l = [1,2,3,4,5]
#用filter把3去除
print(list(filter(lambda x:x != 3,l)))  #取出列表里的值
#交给lambda函数x=1,2,3,4,5,后面这个条件如果返回的是False就不要了,如果是True就收下

sorted  排序
l = ['jason','egon','nick','tank'] # print(sorted(l)) #从小到大排列 print(sorted(l,reverse=True)) #降序 从大到小

reduce 需要从一个模块里面倒
from functools import reduce
#类似于一个工厂  给多份材料返回一个文件
#给一个列表  只会返回一个值
l = [1,2,3,4,5,6]
print(reduce(lambda x,y:x+y,l,19))   #19初始值  第一个参数
#当初始值不存在的情况下  按照下面的规律
#当没有传参数的时候,它首先原理不变,把一个大的列表里面的多个元素,整合成一个元素
#按照前面lambda匿名函数规则来整,这是它不变的方针
#它变在第一次取函数的时候它会一次性取两个元素相加,因为一个数没办法相加
#之后每一次获取一个,与上一次相加的结果再相加

  



posted @ 2019-07-14 02:51  Aomur  阅读(182)  评论(0编辑  收藏  举报