• Python之路(第七篇)Python作用域、匿名函数、函数式编程、map函数、filter函数、reduce函数


    一、作用域


    return 可以返回任意值
    例子

    def test1():
        print("test1")
    def test():
        print("test")
        return test1
    res  = test()
    print(res)
    

      

    输出结果

    test
    <function test1 at 0x021F5C90>
    

      


    分析:这里print(res)输出的是test1函数在内存中的地址,return也是可以返回的
    ,加上括号就可以运行函数了

    例子2

    name = "pony"
    def test1():
        name = "nicholas"
        def inner():
            name = "jack"
            print(name)
        return inner
    res  = test1()
    print(res)
    res()
    

      

    输出结果

    <function test1.<locals>.inner at 0x02195C48>
    jack
    

      

    分析:
    test1函数返回了inner函数的内存地址,并被赋值给res,所以最后在res后加上括号就可以直接执行,注意这里执行的是inner函数,打印name选择的是局部变量name ="jack",而非选择调用执行的res()所在的name = "pony"


    例子3

    def foo():
        name = 'jack'
        def bar():
            name = 'pony'
            print(name)
            def tt():
                print(name)
            return tt
        return bar
    r1 = foo() #返回的是bar函数的内存地址
    r2 = r1()  #执行了bar函数,返回了tt函数的内存地址
    r3 = r2()  #执行了tt函数,输出 pony
    

      

    输出结果

    pony
    pony
    

      

    分析:r1是执行foo函数,最后得到的是bar函数的内存地址,r2是执行了bar函数,返回了tt函数的内存地址,执行了tt函数,输出 pony。
    这里也可以直接这样写
    foo()()()
    foo()是r1,foo()()是r2,foo()()()就是r3.

    二、匿名函数

    1、lambda

    例子


    lambda x:x+1
    这里的x相当于自定义函数的形参,x+1相当于return的返回值
    def calc(x)
    return x+1
    这个自定义函数和lambda x:x+1是等价的

    lambda函数一般用直接是处理加减法、乘法、加字符串
    例子

    def calc(x):
        return x+1
    res = calc(10)
    print(res)
    print(calc)
    

      

    输出结果

    11
    <function calc at 0x02245C48>
    

      

    例子2

    print(lambda x:x+1)
    

      


    输出结果

    <function <lambda> at 0x021B5C48>
    

      

    分析:这里是lambda函数在内存中的地址,和calc函数是一样的(未执行,即未加括号的情况下 )

    调用lambda()

    例子

    func = lambda x:x+1
    res = func(10)
    print(res)
    

      

    输出

    11
    

      


    分析:调用lambda函数需要将lambda函数赋值给一个变量,执行时用变量名加()带参数执行,这里括号内的参数类似自定义函数的实参,通过调用传给形参。

    例子3

    print(list(filter(lambda x:x if x % 2 == 0 else "" ,range(10))))
    

      输出结果

    [2, 4, 6, 8]
    

      分析:lambda可以用if -else语句,但是不能单独用if语句,必须if-else语句一起写

    2、lambda返回多个值


    例子

    func = lambda x,y,z:x + y + z
    res = func(10,11,12)
    print(res)
    #或者这样写
    print(func(10,11,12))
    

      

    例子2

    func = lambda x,y,z:(x + 1 ,y + 1,z +1)
    res = func(10,11,12)
    print(res)
    #或者直接这样写
    print(func(10,11,12))
    

      

    输出结果

    (11, 12, 13)
    (11, 12, 13)
    

      

    分析:这里返回多个值需要用括号和逗号


    三、函数式编程

    1、编程的三种方法论

    面向过程编程、函数式编程、面向对象编程

    面向过程:
    定义
    是一种以过程为中心的编程思想。这些都是以什么正在发生为主要目标进行编程,不同于面向对象的是谁在受影响。
    简单的就是把任务分为一个一个的步骤,一步一步的执行。

    函数式编程:
    定义
    在计算机科学里,函数式编程是一种编程范式,它将计算描述为表达式求值并避免了状态和数据改变。函数式编程里面的“函数”指的是数学函数。

    对于任何一个编程函数,需要满足下面3个条件,即可转换成纯数学函数。

    每个函数必须包含输入参数(作为自变量)
    每个函数必须有返回值(作为因变量)
    无论何时,给定参数调用函数时,返回值必须一致。

    面向对象编程
    定义

    面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。

    而面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。


    2、函数式编程递归调用

    高阶函数的定义
    (1)函数名可以当做参数传递
    (2)返回值可以是参数


    例子

    def foo(n): #n=bar
        print(n)
    
    def bar(name):
        print('my name is %s' %name)
    foo(bar)
    foo(bar("nicholas"))
    

      

    输出结果

    <function bar at 0x02225C48>
    my name is nicholas
    None
    

      


    分析:这里的foo(bar),其中的bar是作为一个函数当做参数传入foo(),bar是一个内存地址。foo(bar("nicholas"))中,bar("nicholas")执行函数,先输出my name is nicholas,然后执行foo函数,由于bar函数没有return出数值,所以执行foo()输出None。


    3、尾调用优化(尾递归优化)

    尾调用:在函数的最后一步调用另外一个函数(最后一行不一定是函数的最后一步)

    例子

    def bar(n):
        return  n
    def foo(x):
        return bar(x)
    

      


    这里的return bar()就是函数的最后一步。

    例子

    def test(x):
        if x > 1:
            return True
        elif x == 1:
            return False
        else:
            return False
    test(1)
    

      

    分析:这里的最后一步是执行elif x ==1下面的 return False语句。

    尾递归与非尾递归
    非尾递归

    def cal(seq):
        if len(seq) == 1:
            return  seq[0]
        head , *tail = seq
        return  head + cal(tail)
    print(cal(range(100)))
    

      

    尾递归

    def cal(l):
        print(l)
        if len(l) == 1:
            return  l[0]
        frist,second,*args = l
        l[0] = frist + second
        l.pop(1)
        return cal(l)
    x = cal([i for i in range(10)])
    print(x)
    

      


    3、 map()函数


    map() 会根据提供的函数对指定序列做映射。

    map(function, iterable, ...)
    function -- 函数,有两个参数
    iterable -- 一个或多个序列
    它有两个参数,第一个参数为某个函数,第二个为可迭代对象。

    例子
    需求,将li1 = [1,3,4,5,7,10] 的每个元素变成自己的平方。


    用for循环解决

    li1 =   [1,3,4,5,7,10]
    li = []
    for i in li1:
        li.append(i ** 2)
    res = li
    print(res)
    

      

    升级需求,处理多个列表,将列表的的每个元素变成自己的平方。

    li1 =   [1,3,4,5,7,10]
    def map_test():
        li = []
        for i in li1:
            li.append(i ** 2)
        return li
    res = map_test(li1)
    print(res)
    

      

    继续升级需求,将原列表的每个元素平方,组成新的列表

    li1 =   [1,3,4,5,7,10]
    def pow_test(n):
        return n ** 2
    def map_test(fun,array):
        li = []
        for i in array:
            res = fun(i)
            li.append(res)
        return li
    res1 = map_test(pow_test,li1)
    print(res1)
    

      

    分析:这里的map_test函数的参数fun传入的是一个函数,即这个map_test函数是高阶函数,在map_test函数里调用其他函数,对第二个传入的对象进行处理。两个这里map_test()、pow_test()加在一起实现的功能就是map()函数的作用。


    这里可以用map()函数处理

    li1 = [1,3,4,5,7,10]
    res1 = list(map(lambda x:x**2,li1))
    print(res1)
    

      

    分析:map()函数的第一个参数是一个函数,即匿名函数,这里不需要加括号执行,只是代表对一个参数的处理方式,map()第二个参数是待处理的可迭代对象。
    map()函数直接处理结果是一个map()函数的内存地址,是一个可迭代类型,需要加list转换为列表。

    这里map()函数的第一个参数不一定非要写lambda函数,也可以写自定义的函数名。


    例子

    def reduce_one(n):
        return n - 1
    li1 =   [1,3,4,5,7,10]
    res1 = list(map(reduce_one,li1))
    print(res1)
    

      

    输出结果

    [0, 2, 3, 4, 6, 9]
    

      



    关于map()函数输出的结果处理

    例子
    用for 循环处理结果

    li1 =   [1,3,4,5,7,10]
    res1 = map(lambda x:x**2,li1)
    for i in res1:
        print(i)
    print(res1)
    

      

    输出结果

    1
    9
    16
    25
    49
    100
    <map object at 0x02185790>
    

      

    直接用map函数

    li1 = [1,3,4,5,7,10]
    res = list(map(lambda x:x**2,li1))
    print("map处理结果是",res)
    

      

    输出结果

    map处理结果是 [1, 9, 16, 25, 49, 100]
    

      

    分析:这里可以看出map()函数直接输出的结果是一个可迭代对象,加上list可以将其转换为列表。


    4、filter()函数


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

    例子
    ,要从一个list [1, 4, 6, 7, 9, 12, 17]中删除偶数,保留奇数

    用自定义函数和for循环解决

    li = [1, 4, 6, 7, 9, 12, 17]
    li1 = []
    def filter_old(n):
        if n % 2 == 1:
            li1.append(n)
    def test():
        for i in li:
            res = filter_old(i)
    test()
    print(li1)
    

      

    输出

    [1, 7, 9, 17]
    

      

    这里也可以直接用filter函数解决。

    li = [1, 4, 6, 7, 9, 12, 17]
    def filter_old(n):
        if n % 2 == 1:
            return n
    res = list(filter(filter_old,li))
    print(res)
    

      


    输出结果

    [1, 7, 9, 17]
    

      

    或者更精简一些

    li = [1, 4, 6, 7, 9, 12, 17]
    res = list(filter(lambda n:n %2 ==1,li))
    print(res)
    

      

    输出结果

    [1, 7, 9, 17]
    

      

    分析:这里的lambda函数是一个函数处理逻辑,最终是返回了符合 n %2 ==1条件的n
    这里与map函数一样,也需要List将其转换为列表。

    例子

    li = [1, 4, 6, 7, 9, 12, 17]
    res = list(filter(lambda n:not n %2 ==1,li))
    print(res)
    

      

    分析:这里的lambda也可以加not。

    例子

    li = [
        {"name":"jack","age":53},
        {"name":"pony","age":46},
        {"name":"charles","age":53},
        {"name":"richard","age":44}
    
    ]
    v = list(filter(lambda p:p["age"]<45,li))
    print(v)
    

      

    输出结果

    [{'name': 'richard', 'age': 44}]
    

      

    分析:这里lambda返回的就是符合条件的元素p,遍历序列中的每个元素,判断每个元素得到布尔值,如果是True则留下来。


    5、reduce()函数


    reduce()在python2中可以直接用
    在python3中需要添加模块导入
    from functools import reduce

    reduce()的使用方法形如reduce(f(x),Itera).对,它的形式和map()函数一样。不过参数f(x)必须有两个参数。reduce()函数作用是:把结果继续和序列的下一个元素做累积计算。

    例子
    需求将列表[1,2,3,4,5,6]所有元素加起来。
    用for循环解决

    li = [1,2,3,4,5,6]
    sum = 0
    for i in li:
        sum = sum + i
    print(sum)
    

      

    需求2,求列表li = [1,2,3,4,5,6]每个元素相乘最终结果

    用自定义函数处理

    li = [1,2,3,4,5,6]
    def test(x,y):
        return x*y
    def test1(func,array):
        res = array.pop(0)
        #这里表示列表的第一个元素
        #pop()删除某个值,并可以获取当前删除的值
        for i in array:
            res = func(res,i)
            #这里是传入的相乘的结果和下一个元素,初始值为res = array[0]。
        return res
    v = test1(test,li)
    print(v)
    

      

    输出结果

    720
    

      

    分析:这里是自定义了2个函数,通过函数中调用另一个函数处理。这里也可以直接用reduce()函数处理。

    from functools import reduce
    li = [1,2,3,4,5,6]
    v = reduce(lambda x,y:x*y,li)
    print(v)
    

      

    输出

    720
    

      

    分析:注意这里不再使用list方法。

    reduce 有 三个参数
    function 有两个参数的函数, 必需参数
    sequence tuple ,list ,dictionary, string等可迭代对象,必需参数
    initial 初始值, 可选参数

    如果没有初始值init,直接执行将第二个参数可迭代对象通过第一个参数func进行处理。
    如果有初始值Init,则首先进行初始值和待传入的第二个参数的第一个元素通过func进行处理,之后这个累计值再和第二个元素进行累计。

    例子

    from functools import reduce
    li = [1,2,3,10]
    v = reduce(lambda x,y:x*y,li,10)
    print(v)
    

      


    输出结果

    600
    

      


    分析:这里首先将初始值10 * 1 得到10,然后用累计值10 *2 得到20,然后20*3,以此类推,最后得到600.

    6、map()、filter()、reduce()小结

    map()
    处理序列中的每个元素,得到的结果是一个‘列表’(内存地址),该‘列表’元素个数及位置与原来一样

    filter()
    filter遍历序列中的每个元素,判断每个元素得到布尔值,如果是True则留下来

    reduce()

    处理一个序列,然后把序列进行合并操作

  • 相关阅读:
    接收一次性广播,开启服务永久监听
    iOS开发之主题皮肤
    Android软件版本更新
    android服务Service(上)- IntentService
    Android之条码扫描二维码扫描
    Android之Service与IntentService的比较
    强烈推荐visual c++ 2012入门经典适合初学者入门
    转载文章:Windows Azure 七月份更新:SQL 数据库、流量管理器、自动伸缩、虚拟机
    CSV 客座文章系列:KGroup 通过 Windows Azure 将 Qoob 内容管理发布到云中
    Windows Azure 网站:应用程序字符串和连接字符串的工作原理
  • 原文地址:https://www.cnblogs.com/Nicholas0707/p/8653170.html
Copyright © 2020-2023  润新知