• Day10:内置函数、匿名函数、递归函数


    一.内置函数

    1.数学运算类

     

    2.集合类操作

     

    内置函数个别使用示例

    1.any 集合中的元素有一个为真的时候为真, 特别的,若为空串返回为False

     

    1 print(any([0,'']))
    2 print(any([0,'',1]))

    执行结果

    1 False
    2 True

    2.divmod 取商得余数,用于做分页显示功能

    1 print(divmod(10,3))    #取商得余数,用于做分页显示

    执行结果

    1 (3, 1)

    3.eval  把字符串中的数据结构给提取出来

    1 dic={'name':'alex'}  #字典类型转成字符串
    2 dic_str=str(dic)
    3 print(dic_str)
    4 
    5 d1=eval(dic_str)     #eval:把字符串中的数据结构给提取出来
    6 print(d1)

    执行结果

    1 {'name': 'alex'}
    2 
    3 {'name': 'alex'}

     4.可hash的数据类型即不可变数据类型,不可hash的数据类型即可变数据类型

     1 #hash的作用:去网上下载软件,判断是否被人修改,通过比对hash值,就知道
     2 print(hash('12sdfdsaf3123123sdfasdfasdfasdfasdfasdfasdfasdfasfasfdasdf'))
     3 print(hash('12sdfdsaf31231asdfasdfsadfsadfasdfasdf23'))
     4 
     5 name='alex'
     6 print(hash(name))
     7 print(hash(name))
     8 
     9 print('--->before',hash(name))
    10 name='sb'
    11 print('=-=>after',hash(name))

    执行结果

    1 1982976672
    2 864959982
    3 -2006403263
    4 -2006403263
    5 --->before -2006403263
    6 =-=>after 805524431

    5.bin、hex、oct  进制转换

    1 print(bin(10))   #10进制->2进制
    2 print(hex(12))   #10进制->16进制
    3 print(oct(12))   #10进制->8进制

    执行结果

    1 0b1010     #10进制->2进制
    2 0xc        #10进制->16进制
    3 0o14       #10进制->8进制

    6.isinstance判断类型

    1 print(isinstance(1,int))       #判断是不是int类型
    2 print(isinstance('abc',str))   #判断字符串
    3 print(isinstance([],list))     #判断列表
    4 print(isinstance({},dict))     #判断字典
    5 print(isinstance({1,2},set))   #判断集合

    执行结果

    1 True
    2 True
    3 True
    4 True
    5 True

    7.max 最大值 和 min最小值

    1 l=[1,3,100,-1,2]
    2 print(max(l))
    3 print(min(l))

    执行结果

    1 100  #最大值
    2 -1     #最小值

    max 高级用法

     

    说明:

     

    1、max函数处理的是可迭代对象,相当于一个for循环取出每个元素进行比较

     

    注意:不同类型之间不能进行比较

     

    2、每个元素间进行比较,是从每个元素的第一位置依次比较,如果这一个位置分出大小,后

     

    面的都不需要比较了,直接得出这俩元素的大小。

    1 age_dic={'alex_age':18,'wupei_age':20,'zsc_age':100,'lhf_age':30}
    2 print(max(age_dic.values()))   #取出最大年龄
    3 print(max(age_dic))            #默认比较的是字典的key

    执行结果

    1 100
    2 zsc_age

    ps:  取出年龄最大的key和values

    1 age_dic={'alex_age':18,'wupei_age':20,'zsc_age':100,'lhf_age':30}
    2 for item in zip(age_dic.values(),age_dic.keys()):  #[(18,'alex_age')  (20,'wupeiqi_age') () () ()]
    3     print(item)
    4 
    5 #取出年龄最大的key和values
    6 print('=======>',list(max(zip(age_dic.values(),age_dic.keys()))))  #max和zip联合使用

    执行结果

    1 (100, 'zsc_age')
    2 (30, 'lhf_age')
    3 (18, 'alex_age')
    4 (20, 'wupei_age')
    5 
    6 
    7 =======> [100, 'zsc_age']  #取出年龄最大的key和values

    ps.

     1 l=[
     2     (5,'e'),
     3     (1,'b'),
     4     (3,'a'),
     5     (4,'d'),
     6 ]
     7 l1=['a10','b12','c10',100]   #不同类型之间不能进行比较
     8 l1=['a10','a2','a10']        #不同类型之间不能进行比较
     9 print(list(max(l)))
    10 
    11 print('--->',list(max(l1)))

    执行结果

    1 [5, 'e']
    2 ---> ['a:', '2']

    8.zip  将对象逐一配对

    PS1

    1 print(list(zip(('a','n','c'),(1,2,3))))
    2 print(list(zip(('a','n','c'),(1,2,3,4))))
    3 print(list(zip(('a','n','c','d'),(1,2,3))))

    执行结果

    1 [('a', 1), ('n', 2), ('c', 3)]
    2 [('a', 1), ('n', 2), ('c', 3)]
    3 [('a', 1), ('n', 2), ('c', 3)]

    ps2:

    1 p={'name':'alex','age':18,'gender':'none'}
    2 print(list(zip(p.keys(),p.values())))
    3 print(list(p.keys()))    #取keys
    4 print(list(p.values()))  #values
    5 
    6 print(list(zip(['a','b'],'12345')))   #列表,只要是序列就可以打印出来

    执行结果

    1 [('age', 18), ('name', 'alex'), ('gender', 'none')]
    2 ['age', 'name', 'gender']
    3 [18, 'alex', 'none']
    4 [('a', '1'), ('b', '2')]

    PS3:总结

     1 l=[1,3,100,-1,2]
     2 print(max(l))    #比较出最大值
     3 
     4 
     5 dic={'age1':18,'age2':10}
     6 print(max(dic))           #比较的是key
     7 
     8 
     9 print(max(dic.values()))  #比较的是key,但是不知道是那个key对应的值
    10 
    11 
    12 print(max(zip(dic.values(),dic.keys())))   #结合zip使用

    执行结果

    1 100    #比较大小,得出最大值   
    2 
    3 age2   #比较的是key
    4 
    5 18     #比较的是key,但是不知道是那个key对应的值
    6 
    7 (18, 'age1')   #结合zip拿用

    ps:

     1 people=[
     2     {'name':'alex','age':1000},
     3     {'name':'wupei','age':10000},
     4     {'name':'yuanhao','age':9000},
     5     {'name':'linhaifeng','age':18},
     6 ]
     7 # max(people,key=lambda dic:dic['age'])
     8 print(max(people,key=lambda dic:dic['age']))    #提取年龄中的values,再进行比较
     9 
    10 #上面题分解步骤,先取出ret的值,再给max进行比较
    11 people=[
    12     {'name':'alex','age':1000},
    13     {'name':'wupei','age':10000},
    14     {'name':'yuanhao','age':9000},
    15     {'name':'linhaifeng','age':18},
    16 ]
    17 
    18 ret=[]
    19 for item in people:
    20     ret.append(item['age'])
    21 print(ret)
    22 max(ret)

    执行结果

    1 #提取年龄中的values,再进行比较大小,得出age最大的
    2 
    3{'name': 'wupei', 'age': 10000}
    4 
    5 
    6 #上面题分解步骤,先取出ret的值,再给max进行比较,得出的值:
    7 
    8 [1000, 10000, 9000, 18]

    9.reversed 反转

    1 l=[1,2,3,4]
    2 print(list(reversed(l)))
    3 print(l)

    执行结果

    1 [4, 3, 2, 1]   #反转
    2 [1, 2, 3, 4]

    10.round  四舍五入

    1 print(round(3.5))   #四舍五入

    执行结果

    1 4

    11.slice 切片

     1 l='hello'
     2 s1=slice(3,5)    #切片 取3到5的元素
     3 s2=slice(1,4,2)  #切片,指定步长为2
     4 print(l[3:5])
     5 
     6 print(l[s1])   #切片
     7 print(l[s2])
     8 
     9 print(s2.start)  #开始
    10 print(s2.stop)   #结束
    11 print(s2.step)   步长

    执行结果

     1 lo
     2 
     3 lo
     4 
     5 el
     6 
     7 1
     8 
     9 4
    10 
    11 2

    12.sorted 排序

    ps1:

    1 l=[3,2,1,5,7]
    2 l1=[3,2,'a',1,5,7]
    3 print(sorted(l))    #排序
    4 # print(sorted(l1)) #直接运行会报错,因为排序本质就是在比较大小,不同类型之间不可以比较大小

    执行结果

    1 [1, 2, 3, 5, 7]

    ps2:

    1 people=[
    2     {'name':'alex','age':1000},
    3     {'name':'wupei','age':10000},
    4     {'name':'yuanhao','age':9000},
    5     {'name':'linhaifeng','age':18},
    6 ]
    7 print(sorted(people,key=lambda dic:dic['age']))    #按年龄进行排序

    执行结果

    1 [{'age': 18, 'name': 'linhaifeng'}, {'age': 1000, 'name': 'alex'}, {'age': 9000, 'name': 'yuanhao'}, {'age': 10000, 'name': 'wupei'}]

    ps3:

     1 name_dic={
     2     'abyuanhao': 11900,
     3     'alex':1200,
     4     'wupei':300,
     5 }
     6 print(sorted(name_dic))   #按key排序
     7 
     8 print(sorted(name_dic,key=lambda key:name_dic[key]))   #取出字典的values
     9 
    10 print(sorted(zip(name_dic.values(),name_dic.keys())))   #按价格从低到高排序

    执行结果

    1 ['abyuanhao', 'alex', 'wupei']
    2 
    3 ['wupei', 'alex', 'abyuanhao']
    4 
    5 [(300, 'wupei'), (1200, 'alex'), (11900, 'abyuanhao')]

     

    3.高阶函数

    map()函数接收两个参数,一个是函数,一个是Iterablemap将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。

    举例说明,比如我们有一个函数f(x)=x2,要把这个函数作用在一个list [1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用map()实现如下:

    现在,我们用Python代码实现:

    >>> def f(x):
    ...     return x * x
    ...
    >>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
    >>> list(r)
    [1, 4, 9, 16, 25, 36, 49, 64, 81]

    map()传入的第一个参数是f,即函数对象本身。由于结果r是一个IteratorIterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。

    你可能会想,不需要map()函数,写一个循环,也可以计算出结果:

    L = []
    for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]:
        L.append(f(n))
    print(L)

    的确可以,但是,从上面的循环代码,能一眼看明白“把f(x)作用在list的每一个元素并把结果生成一个新的list”吗?

    所以,map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x2,还可以计算任意复杂的函数,比如,把这个list所有数字转为字符串:

    >>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
    ['1', '2', '3', '4', '5', '6', '7', '8', '9']

    只需要一行代码。

    再看reduce的用法。reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:

    reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

    比方说对一个序列求和,就可以用reduce实现:

    >>> from functools import reduce
    >>> def add(x, y):
    ...     return x + y
    ...
    >>> reduce(add, [1, 3, 5, 7, 9])
    25

    当然求和运算可以直接用Python内建函数sum(),没必要动用reduce

    但是如果要把序列[1, 3, 5, 7, 9]变换成整数13579reduce就可以派上用场:

    >>> from functools import reduce
    >>> def fn(x, y):
    ...     return x * 10 + y
    ...
    >>> reduce(fn, [1, 3, 5, 7, 9])
    13579

    这个例子本身没多大用处,但是,如果考虑到字符串str也是一个序列,对上面的例子稍加改动,配合map(),我们就可以写出把str转换为int的函数:

    >>> from functools import reduce
    >>> def fn(x, y):
    ...     return x * 10 + y
    ...
    >>> def char2num(s):
    ...     return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
    ...
    >>> reduce(fn, map(char2num, '13579'))
    13579

    整理成一个str2int的函数就是:

    from functools import reduce
    
    def str2int(s):
        def fn(x, y):
            return x * 10 + y
        def char2num(s):
            return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
        return reduce(fn, map(char2num, s))

    还可以用lambda函数进一步简化成:

    from functools import reduce
    
    def char2num(s):
        return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
    
    def str2int(s):
        return reduce(lambda x, y: x * 10 + y, map(char2num, s))

     二.匿名函数

    当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。

    匿名函数没有函数名,只使用一次。

    在Python中,对匿名函数提供了有限支持。还是以map()函数为例,计算f(x)=x2时,除了定义一个f(x)的函数外,还可以直接传入匿名函数:

    >>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
    [1, 4, 9, 16, 25, 36, 49, 64, 81]

    通过对比可以看出,匿名函数lambda x: x * x实际上就是:

    def f(x):
        return x * x

    关键字lambda表示匿名函数,冒号前面的x表示函数参数。

    匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。

    用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:

    >>> f = lambda x: x * x
    >>> f
    <function <lambda> at 0x101c6ef28>
    >>> f(5)
    25

    同样,也可以把匿名函数作为返回值返回,比如:

    def build(x, y):
        return lambda: x * x + y * y

    三.递归

    在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

    举个例子,我们来计算阶乘n! = 1 x 2 x 3 x ... x n,用函数fact(n)表示,可以看出:

    fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n

    所以,fact(n)可以表示为n x fact(n-1),只有n=1时需要特殊处理。

    于是,fact(n)用递归的方式写出来就是:

    def fact(n):
        if n==1:
            return 1
        return n * fact(n - 1)

    上面就是一个递归函数。可以试试:

    >>> fact(1)
    1
    >>> fact(5)
    120
    >>> fact(100)
    93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
    如果我们计算fact(5),可以根据函数定义看到计算过程如下:
    ===> fact(5)
    ===> 5 * fact(4)
    ===> 5 * (4 * fact(3))
    ===> 5 * (4 * (3 * fact(2)))
    ===> 5 * (4 * (3 * (2 * fact(1))))
    ===> 5 * (4 * (3 * (2 * 1)))
    ===> 5 * (4 * (3 * 2))
    ===> 5 * (4 * 6)
    ===> 5 * 24
    ===> 120

    递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

    使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。可以试试fact(1000)

    >>> fact(1000)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 4, in fact
      ...
      File "<stdin>", line 4, in fact
    RuntimeError: maximum recursion depth exceeded in comparison

    解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。

    尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

    上面的fact(n)函数由于return n * fact(n - 1)引入了乘法表达式,所以就不是尾递归了。要改成尾递归方式,需要多一点代码,主要是要把每一步的乘积传入到递归函数中:

    def fact(n):
        return fact_iter(n, 1)
    
    def fact_iter(num, product):
        if num == 1:
            return product
        return fact_iter(num - 1, num * product)

    可以看到,return fact_iter(num - 1, num * product)仅返回递归函数本身,num - 1num * product在函数调用前就会被计算,不影响函数调用。

    fact(5)对应的fact_iter(5, 1)的调用如下:

    ===> fact_iter(5, 1)
    ===> fact_iter(4, 5)
    ===> fact_iter(3, 20)
    ===> fact_iter(2, 60)
    ===> fact_iter(1, 120)
    ===> 120
    

    尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。

    遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。

    def age(n):
        if n == 5:
            return 18
        return age(n+1)+2
    
    
    print(age(1))
    l=[1,[2,3,[4,5,[6,7,[8,9,[10,11,[12,13]]]]]]]
    def func(l):
        for i in l:
            if isinstance(i,list):
                func(i)
            else:
                print(i)
    
    func(l)

    四.课后作业

    1、文件内容如下,标题为:姓名,性别,年纪,薪资

    egon male 18 3000

    alex male 38 30000

    wupeiqi female 28 20000

    yuanhao female 28 10000

    要求:

    从文件中取出每一条记录放入列表中,

    列表的每个元素都是{'name':'egon','sex':'male','age':18,'salary':3000}的形式

    1 salary_info=[{'name':line.split()[0],'sex':line.split()[1],'age':int(line.split()[2]),'salary':int(line.split()[3])} for line in open('xinxi.txt',encoding='utf-8')]
    2 print(salary_info)

    [{'name': 'egon', 'sex': 'male', 'age': 18, 'salary': 3000},

     {'name': 'alex', 'sex': 'male', 'age': 38, 'salary': 30000},

     {'name': 'wupeiqi', 'sex': 'female', 'age': 28, 'salary': 20000},

     {'name': 'yuanhao', 'sex': 'female', 'age': 28, 'salary': 10000}]

    2、根据1得到的列表,取出薪资最高的人的信息

    print([i for i in max(salary_info,key=lambda x:x['salary']).values()])
    
    #执行结果
    
    ['alex', 'male', 38, 30000]

    3、根据1到的列表,取出最年轻的人的信息

    print([i for i in min(salary_info,key=lambda x:x['age']).values()])
    
    #执行结果
    
     ['egon', 'male', 18, 3000]

    4、根据1得到的列表,将每个人的信息中的名字映射成首字母大写的形式

    print(list(map(lambda x:x['name'].capitalize(),salary_info))) 
    
    #执行结果
    
    
    ['Egon', 'Alex', 'Wupeiqi', 'Yuanhao']

    5、根据1得到的列表,过滤掉名字以a开头的人的信息

    print(list(filter(lambda x:not x['name'].startswith('a'),salary_info)))
    
    #执行结果
    
    
    [{'name': 'egon', 'sex': 'male', 'age': 18, 'salary': 3000},
    
     {'name': 'wupeiqi', 'sex': 'female', 'age': 28, 'salary': 20000},
    
     {'name': 'yuanhao', 'sex': 'female', 'age': 28, 'salary': 10000}]

    6、使用递归打印斐波那契数列(前两个数的和得到第三个数) 0 1 1 2 3 5 8...

    def fi(n):
        if n==0:
            return 0
        if n==1 or n==2:
            return 1
        return fi(n-1)+fi(n-2)
    print([fi(i) for i in range(20)])
    
    
     
  • 相关阅读:
    NOIP 转圈游戏
    NOIP 2012 同余方程
    BZOJ3864 Hero meet devil
    HDU3045 Picnic Cows
    「PKUWC2018」随机算法
    CF543E Listening to Music
    CF833E Caramel Clouds
    「PKUWC2018」Slay the Spire
    Luogu2183【国家集训队】礼物
    CF932E Team Work
  • 原文地址:https://www.cnblogs.com/Vee-Wang/p/7056161.html
Copyright © 2020-2023  润新知