zoukankan      html  css  js  c++  java
  • day19-高阶函数、匿名函数

    map 函数

    map 是一个在 Python 里非常有用的高阶函数。它接受一个函数和一个序列(迭代器)作为输入,然后对序列(迭代器)的每一个值应用这个函数,返回一个序列(迭代器),其包含应用函数后的结果。

    语法
    map(function, iterable, ...)
    参数iterable可以是一个或多个序列

    例子
    1、计算平方数

    def square(x):
        return x ** 2
    lst = map(square, [1,2,3,4,5])
    print(list(lst))
    #[1, 4, 9, 16, 25]

    使用 lambda 匿名函数

    lst2 = map(lambda x:x**2, [1,2,3,4,5])
    print(list(lst2))
    #[1, 4, 9, 16, 25]

    2、提供了两个列表,对相同位置的列表数据进行相加

    lst3 = map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
    print(list(lst3))
    #[3, 7, 11, 15, 19]

    3、假设用户输入的英文名字不规范,没有按照首字母大写,后续字母小写的规则,请利用map()函数,把一个list(包含若干不规范的英文名字)变成一个包含规范英文名字的list:

    输入:['adam', 'LISA', 'barT']
    输出:['Adam', 'Lisa', 'Bart']

    name_list = ['adam', 'LISA', 'barT']
    
    def format_name(s):
        return s.lower().capitalize()
    print(list(map(format_name, name_list)))

    或使用匿名函数

    print(list(map(lambda x:x.capitalize(), name_list)))

    filter函数

    filter()函数是 Python 内置的另一个有用的高阶函数,filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。

    例如,要从一个list [1, 4, 6, 7, 9, 12, 17]中删除偶数,保留奇数,首先,要编写一个判断奇数的函数,然后,利用filter()过滤掉偶数:

    def is_odd(x):
        return x % 2 == 1
    
    filter(is_odd, [1, 4, 6, 7, 9, 12, 17])
    结果:[1, 7, 9, 17]

    利用filter(),可以完成很多有用的功能,例如,删除 None 或者空字符串:

    def is_not_empyt(s):
        return s and len(s.split()) > 0
    newlist = filter(is_not_empyt, ['1', 'str', '', ' '])
    print(list(newlist))
    
    ['1', 'str']

    关于filter()方法, python3和python2有一点不同
    Python2.x 中返回的是过滤后的列表, 而 Python3 中返回到是一个 filter 类。
    filter 类实现了 __iter__ 和 __next__ 方法, 可以看成是一个迭代器, 有惰性运算的特性, 相对 Python2.x 提升了性能, 可以节约内存。

    a = filter(lambda x: x % 2 == 0, range(10))
    print(a)
    
    输出
    <filter object at 0x0000022EC66BB128>

    所以在python3中输出需要用print(list(a))

    例子
    请利用filter()过滤出1~100中平方根是整数的数,即结果应该是:
    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

    filter()接收的函数必须判断出一个数的平方根是否是整数,而math.sqrt()返回结果是浮点数,所以没办法用isinstance判断数据类型是整数

    方法一:
        import math
        def is_sqr(x):
            r = int(math.sqrt(x))
            return r*r==x
        print filter(is_sqr, range(1, 101))
    
    方法二:
    import math
    def my_sqrt(x):
        return math.sqrt(x) % 1 == 0
    lst = filter(my_sqrt, range(1,101))
    print(list(lst))

    reduce函数

    reduce()函数也是Python内置的一个高阶函数。reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。
    在python2中可直接使用reduce()函数
    在Python3里,reduce()函数已经被从全局名字空间里移除了,它现在被放置在functools模块里,用的话要先引入from functools import reduce

    语法
    reduce(function, iterable[, initializer])

    参数
    function -- 函数
    iterable -- 可迭代对象
    initializer -- 可选,初始参数

    例如,编写一个f函数,接收x和y,返回x和y的和:
    def f(x, y):
        return x + y

    调用 reduce(f, [1, 3, 5, 7, 9])时,reduce函数将做如下计算:
    先计算头两个元素:f(1, 3),结果为4;
    再把结果和第3个元素计算:f(4, 5),结果为9;
    再把结果和第4个元素计算:f(9, 7),结果为16;
    再把结果和第5个元素计算:f(16, 9),结果为25;
    由于没有更多的元素了,计算结束,返回结果25。

    上述计算实际上是对 list 的所有元素求和。虽然Python内置了求和函数sum(),但是,利用reduce()求和也很简单。

    reduce()还可以接收第3个可选参数,作为计算的初始值。如果把初始值设为100,计算:
    reduce(f, [1, 3, 5, 7, 9], 100)
    结果将变为125,因为第一轮先计算初始值和第一个元素:f(100, 1),结果为101。

    例子
    Python内置了求和函数sum(),但没有求积的函数,请利用recude()来求积:
    输入:[2, 4, 5, 7, 12]
    输出:2*4*5*7*12的结果

    lst1 = [2, 4, 5, 7, 12]
    
    from functools import reduce
    def prod(x, y):
        return x*y
    print(reduce(prod, lst1))

    sorted函数

    sorted()也是一个高阶函数,可以接收可迭代对象、比较函数、比较的元素和排序规则

    语法:
    sorted(iterable[, cmp[, key[, reverse]]])

    参数说明:
    iterable -- 可迭代对象。
    cmp -- 比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0。
    key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
    reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
    Python 3.X 的版本中已经没有cmp函数,使用key即可

    python2中它可以接收一个比较函数来实现自定义排序,比较函数的定义是,传入两个待比较的元素 x, y,如果 x 应该排在 y 的前面,返回 -1,如果 x 应该排在 y 的后面,返回 1。如果 x 和 y 相等,返回 0。

    因此,如果我们要实现倒序排序,只需要编写一个reversed_cmp函数:

    def reversed_cmp(x, y):
        if x > y:
            return -1
        if x < y:
            return 1
        return 0

    这样,调用 sorted() 并传入 reversed_cmp 就可以实现倒序排序:

    print(sorted([36, 5, 12, 9, 21], cmp = reversed_cmp))
    [36, 21, 12, 9, 5]

    sorted()函数可以接收一个key函数来实现自定义的排序,例如按绝对值大小排序:

    list = [1,3,5,-10,12,-15]
    result = sorted(list,key=abs)
    print(result)
    [1, 3, 5, -10, 12, -15]

    reverse=True反向排序

    print(sorted([36, 5, 12, 9, 21], reverse=True))
    [36, 21, 12, 9, 5]

    sorted()也可以对字符串进行排序,字符串默认按照ASCII大小来比较:

    print(sorted(['bob', 'about', 'Zoo', 'Credit']))
    ['Credit', 'Zoo', 'about', 'bob']

    'Zoo'排在'about'之前是因为'Z'的ASCII码比'a'小。

    对字符串排序时,有时候忽略大小写排序更符合习惯。利用sorted()高阶函数,实现忽略大小写排序的算法。

    a = ['bob', 'about', 'Zoo', 'Credit']
    print (sorted(a, key=lambda x:x.upper()))
    ['about', 'bob', 'Credit', 'Zoo']
    
    a = ['bob', 'about', 'Zoo', 'Credit']
    print (sorted(a, key=str.lower))
    ['about', 'bob', 'Credit', 'Zoo']

    要进行反向排序,不必改动key函数,可以传入第三个参数reverse=True:

    print(sorted(a, key=str.lower, reverse=True))
    ['Zoo', 'Credit', 'bob', 'about']

    python2中可以利用cmp函数

    L=[('b',2),('a',1),('c',3),('d',4)]
    print sorted(L, cmp=lambda x,y:cmp(x[1],y[1]))   
    [('a', 1), ('b', 2), ('c', 3), ('d', 4)]

    利用key

    print(sorted(L, key=lambda x:x[1]))             
    [('a', 1), ('b', 2), ('c', 3), ('d', 4)]

    按年龄排序

    students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
    print(sorted(students, key=lambda s: s[2]))            
    [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

    按降序

    print(sorted(students, key=lambda s: s[2], reverse=True))       
    [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

    匿名函数

    python使用lambda来创建匿名函数。lambda只是一个表达式,函数体比def简单很多。
    lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑。
    lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
    虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

    语法
    lambda [arg1 [,arg2,.....argn]]:expression
    lambda a:b,其中a表示参数,b表示返回值。

    以下代码能运行吗?
        l = [1,2,3,4,5]  
        for i in range(0,len(l)):  
            print i  
            if l[i] % 2 == 0:  
                del l[i]  
        print l  
    
    结果:
    [python] view plain copy
        Traceback (most recent call last):  
          File "D:1.py", line 3, in <module>  
            if l[i] % 2 == 0:  
        IndexError: list index out of range  

    因为随着del()语句的执行,list的元素越来越少,但是for已经定了[0,5):
    i = 0,l[i] = 1不是偶数跳过
    i = 1,l[i] = 2是偶数,l = [1,3,4,5]
    i = 2,l[i] = 4是偶数,l=[1,3,5]
    i = 3,l[i] 越界了,list index out of range。

    以下代码能运行吗?
    [python] view plain copy
        ll = [1,2,3,4,5]  
        for i in ll:  
            if i % 2 == 0:  
                ll.remove(i)     
        print ll  
    
    结果:[1, 3, 5]  

    这段代码就没上述的问题。list有多少就取多少。

    用filter()和lambda实现上面的功能:

    print(list(filter(lambda x:x%2==0,range(10))))
    [0, 2, 4, 6, 8]

    filter(function,list),把list中的元素一个个丢到function中,Return True的元素组成一个new list。

    ll = [1,2,3,4,5]  
    def func(x):  
        return x % 2 != 0  
    print filter(func,ll)

    总结:
    1、循环list的时候,最好用for i in list:,减少因为del()犯下不易察觉的失误。
    2、在python2 中直接打印map,filter函数会直接输出结果。但在python3中做了些修改,输出前需要使用list()进行显示转换。
    3、lambda可以处理的最复杂的情况就是三元运算了,不能再复杂了,比如for循环之类的就不能实现了。

    filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的list。

    print(list(filter(fun,ll)))
    print(list(filter(lambda i:i%2!=0,ll)))

    关键字lambda表示匿名函数,冒号前面的x表示函数参数。
    匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。
    用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:

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

    也可以传入多个参数
    计算n的y次方

    calc = lambda n,y:n**y
    print(calc(2,10))
  • 相关阅读:
    ElasticSearch 2 (10)
    zookeeper 配置
    zookeeper
    ES 聚合函数
    win 7安装 linux
    Elasticsearch分布式搜索集群配置
    Elasticsearch 插件安装
    为Elasticsearch添加中文分词,对比分词器效果
    .net 4.0 网站发布(转)
    ssm 网页
  • 原文地址:https://www.cnblogs.com/dxnui119/p/9956824.html
Copyright © 2011-2022 走看看