zoukankan      html  css  js  c++  java
  • Python之路Python作用域、匿名函数、函数式编程、map函数、filter函数、reduce函数

    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)

     

      

    输出

    1
     

      


    分析:调用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()函数处理。

    rom 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()

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

     

  • 相关阅读:
    常见寻找OEP脱壳的方法
    Windows内核原理系列01
    HDU 1025 Constructing Roads In JGShining's Kingdom
    HDU 1024 Max Sum Plus Plus
    HDU 1003 Max Sum
    HDU 1019 Least Common Multiple
    HDU 1018 Big Number
    HDU 1014 Uniform Generator
    HDU 1012 u Calculate e
    HDU 1005 Number Sequence
  • 原文地址:https://www.cnblogs.com/insane-Mr-Li/p/9813644.html
Copyright © 2011-2022 走看看