• Python基础语法快速复习-函数式编程


    函数式编程语言的特点:允许把函数本身作为参数传入另一个函数,还允许返回一个函数。

    1 高阶函数

    1.1 变量可以指向函数

    对于绝对值函数abs()来说,abs(x)为函数调用,abs是函数本身。

    通过将函数本身赋值给变量达到变量指向函数得的目的

    f = abs
    f(-10)
    
    10
    

    1.2 函数名也是变量

    函数名其实就是指向函数的变量,即函数名abs自身就是一个变量,指向了生成绝对值的函数。

    如果更改原函数的指向后重新调用函数会报错

    abs = 10
    abs(-10)
    
    ---------------------------------------------------------------------------
    
    TypeError                                 Traceback (most recent call last)
    
    <ipython-input-2-dae1c1c42fe8> in <module>
          1 abs = 10
    ----> 2 abs(-10)
    
    
    TypeError: 'int' object is not callable
    

    1.3 传入函数

    一个函数接收另一个函数作为参数,这个函数就被称之为高阶函数

    def add(x,y,f):
        return f(x)+f(y)
    
    add(-5,6,abs)
    
    11
    

    1.4 map/reduce

    map() 函数能够接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到Iterable的每个元素上,结果用Iterator返回。

    def f(x):
        return x*x
    
    r = map(f,list(range(1,10)))
    list(r)
    
    [1, 4, 9, 16, 25, 36, 49, 64, 81]
    

    reduce的作用效果:reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

    传入的函数必须接收两个参数,第二个参数需要时是列表。

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

    1.5 filter

    filter()的主要作用在于过滤序列,filter()同样是接收一个函数和一个序列,不过在将函数作用与每个元素后会根据返回值的布尔类型判断是否丢弃元素。

    #在列表中删除偶数,只保留奇数
    def is_odd(n):
        return n%2 ==1
    
    list(filter(is_odd,[1,2,3,4,5,6,9,10,15]))
    
    [1, 3, 5, 9, 15]
    
    #删除序列中的空字符串
    def not_empty(s):
        return s and s.strip()
    
    list(filter(not_empty, ['A', '', 'B', None, 'C', '  ']))
    
    ['A', 'B', 'C']
    
    #用python实现埃式筛法
    
    #构造从3开始的奇数序列(构造出的为一个生成器,生成无限序列)
    def _odd_iter():
        n = 1
        while True:
            n = n+2
            yield n 
    
    #定义筛选器
    def _not_divisible(n):
        return lambda x:x%n >0
    
    #定义生成器,不断返回下一个素数
    def primes():
        yield 2
        it = _odd_iter()
        while True:
            n = next(it)
            yield n 
            it = filter(_not_divisible(n),it)
    
    for n in primes():
        if n < 1000:
            print(n)
        else:
            break
    
    2
    3
    5
    7
    11
    13
    17
    19
    23
    29
    31
    37
    41
    43
    47
    53
    59
    61
    67
    71
    73
    79
    83
    89
    97
    101
    103
    107
    109
    113
    127
    131
    137
    139
    149
    151
    157
    163
    167
    173
    179
    181
    191
    193
    197
    199
    211
    223
    227
    229
    233
    239
    241
    251
    257
    263
    269
    271
    277
    281
    283
    293
    307
    311
    313
    317
    331
    337
    347
    349
    353
    359
    367
    373
    379
    383
    389
    397
    401
    409
    419
    421
    431
    433
    439
    443
    449
    457
    461
    463
    467
    479
    487
    491
    499
    503
    509
    521
    523
    541
    547
    557
    563
    569
    571
    577
    587
    593
    599
    601
    607
    613
    617
    619
    631
    641
    643
    647
    653
    659
    661
    673
    677
    683
    691
    701
    709
    719
    727
    733
    739
    743
    751
    757
    761
    769
    773
    787
    797
    809
    811
    821
    823
    827
    829
    839
    853
    857
    859
    863
    877
    881
    883
    887
    907
    911
    919
    929
    937
    941
    947
    953
    967
    971
    977
    983
    991
    997
    

    1.6 sorted

    利用sorted函数对列表进行排序

    sorted([36,5,-12,9,-21])
    
    [-21, -12, 5, 9, 36]
    

    接收key函数实现自定义排序,比如按绝对值大小排序

    sorted([36,5,-12,9,-21],key = abs)
    
    [5, 9, -12, -21, 36]
    

    利用sorted对字符串进行排序

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

    忽略字符串的大小写

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

    反向排序

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

    2 返回函数

    2.1 函数作为返回值

    高阶函数不仅可以接收函数作为参数,还可以把参数作为结果返回

    # 实现可变参数求和
    def calc_sum(*args):
        ax = 0
        for n in args:
            ax = ax+n
        return ax
    
    #不返回求和结果,返回求和的函数:
    def lazy_sum(*args):
        def sum():
            ax = 0
            for n in args:
                ax = ax+n
            return ax
        return sum
    
    f = lazy_sum(1,3,5,7,9)
    f
    
    <function __main__.lazy_sum.<locals>.sum()>
    
    f()
    
    25
    

    在函数lazy_sum中定义函数sum,内部函数sum引用外部函数lazy_sum的参数和局部变量,lazy_sum返回函数sum的时候将相关参数和变量都保存在返回的函数中,叫做"闭包"(程序结构)

    2.2 闭包

    def count():
        fs = []
        for i in range(1, 4):
            def f():
                 return i*i
            fs.append(f)
        return fs
    
    f1, f2, f3 = count()
    
    print(f1())
    print(f2())
    print(f3())
    
    9
    9
    9
    

    之所以全部为9的原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9。

    返回闭包时牢记:返回函数不要使用任何循环变量,或者后续产生变化的变量

    3 匿名函数

    通过匿名函数及对应正常写法快速掌握

    #正常写法
    def f(x):
        return x*x
    
    #匿名函数写法
    lambda x:x*x
    

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

    匿名函数可以赋值给变量,让变量来调用

    也可以把匿名函数作为返回值返回

    def build(x,y):
        return lambda x,y:x*x+y*y
    
    print(build(1,2))
    
    <function build.<locals>.<lambda> at 0x000001F21FF113A0>
    

    4 装饰器

    #通过变量调用函数
    
    def now():
        print('2015-3-25')
    
    f = now
    f()
    
    2015-3-25
    

    利用函数对象的__ name __ 属性拿到函数名

    now.__name__
    
    'now'
    

    装饰器(decorator)定义:在代码运行期间动态增加功能的方式(增加函数功能又不改变定义)

    def log(func):
        def wrapper(*args,**kw):
            print('call %s():' % func.__name__)
            return func(*args,**kw)
        return wrapper
    

    装饰器接收一个函数作为参数,返回一个参数,我们需要采用@语法将装饰器置于函数的定义处:

    @log
    def now():
        print('2015-3-25')
    now()
    
    call now():
    2015-3-25
    

    调用now()函数,不仅会运行now()函数本身,还会在运行now()函数前打印一行日志:

    @log与语句now = log(now) 相同

    wrapper()函数的参数定义是(* args, ** kw),因此,wrapper()函数可以接受任意参数的调用。在wrapper()函数内,首先打印日志,再紧接着调用原始函数。

    5 偏函数

    引入

    #字符串转整数
    print(int('12345'))
    
    #利用int()中的base参数进行N进制转换
    print(int('12345',16))
    
    12345
    74565
    

    定义一个二进制转换函数

    def int2(x,base = 2):
        return int(x,base)
    
    int2('1000000')
    
    64
    

    functools.partial帮助创建偏函数,不需要我们自己定义二进制转换函数,使用下面代码即可创建

    import functools
    int2 = functools.partial(int, base=2)
    int2('1000000')
    
    64
    

    当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。

  • 相关阅读:
    hdu 1568 (log取对数 / Fib数通项公式)
    整数对(hdu1271)找规律
    Pupu(hdu3003)数论
    哈密顿绕行世界问题(hdu2181)
    Saving HDU(hdu2111,贪心)
    素数回文(hdu1431)
    Hashmat the brave warrior(UVa10055)简单题
    Moon Game (凸四边形个数,数学题)
    Zipper(poj2192)dfs+剪枝
    不要62(hdu2089)
  • 原文地址:https://www.cnblogs.com/MurasameLory-chenyulong/p/14538325.html
Copyright © 2020-2023  润新知