• Python函数式编程(高阶函数、map/reduce、filter、sorted、匿名函数、返回函数)-3


    • 是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量;函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还返回一个函数。

    一、高阶函数

    • 函数本身也可以赋值给变量,即变量指向函数。
    • 函数名也是变量。
    • 一个函数可以接受另一个函数作为参数,这种函数称之为高阶函数。
    >>> def add(x, y, f): 
    ...     return f(x) + f(y)
    ... 
    >>> print(add(-5, 6, abs)) 
    11
    

    1. map/reduce

    • map()函数接受两个参数,一个函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
    • 因为Iterator是惰性序列(迭代器仅仅至某个元素时才计算),因此通过list()函数让它把整个序列都计算出来并返回一个list。
    >>> def f(x):
    ...     return x * x
    ... 
    >>> r = map(f, [1, 2, 3, 4, 5, 6, 7,8, 9]) 
    >>> r
    <map object at 0x000001C329AA5240>
    >>> list(r) 
    [1, 4, 9, 16, 25, 36, 49, 64, 81]
    
    • reduce把一个函数作用在一个序列[x1, x2, x3, x4...],这个函数必须接收两个参数,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
    

    2. filter

    • filter()函数用于过滤序列,也是两个参数,一个函数一个序列,把传入的函数依次作用于每个元素,然后根据返回值是True或False决定保留还是丢弃该元素,也是返回一个Iterator。
    >>> def not_empty(s):
    ...     return s and s.strip
    ... 
    >>> def not_empty(s):        
    ...     return s and s.strip()  
    ... 
    >>> list(filter(not_empty, ['A', '', "c", None, '  ']))
    ['A', 'c']
    >>>
    

    3. sorted

    • Python内置的sorted()函数就可以对list进行排序。
    • 同时也是一个高阶函数,它可以接受一个key函数来实现自定义的排序,例如按照绝对值大小排序。
    • 默认是从小到大进行排序,如果想要排序相反,则传入第三个参数reverse=True
    >>> sorted([36, 5, -12, 9, -21]) 
    [-21, -12, 5, 9, 36]
    >>> sorted([36, 5, -12, 9, -21], key=abs)
    [5, 9, -12, -21, 36]
    >>> 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']
    

    二、返回函数

    1. 高阶函数除了接受函数作为参数外,还使用函数作为结果返回,但是该函数没有执行。
    2. 我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。
    3. 当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数。
    4. 返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

    三、匿名函数

    1. 关键字lambda表示匿名函数,冒号前面的x表示函数参数
    2. 匿名函数有个限制,就是只能够有一个表达式,不能写return,返回值就是该表达式的结果。
    3. 不用担心函数名冲突,同时也是一个函数对象,也可将其赋给变量,然后调用。
    4. 也可以作为函数的返回值。

    四、装饰器

    1. 函数也是夜歌对象,而且函数对象可以赋值给变量,所以通过变量也能够调用函数。
    2. 函数对象有一个__name__属性,可以拿到函数的名字。
    3. 假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)
    4. 把@log放到now()处,相当于执行了语句now = log(now)
    5. 在面向对象(OOP)的设计模式中,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
    
    def log(text):
        def decorator(func):
            def wrapper(*args, **kw):
                print('%s %s():' % (text, func.__name__))
                return func(*args, **kw)
            return wrapper
        return decorator
    
    @log('execute')
    def now():
        print('2015-3-25')
    
    >>> now()
    execute now():
    2015-3-25
    
    import functools
    
    def log(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('call %s():' % func.__name__)
            return func(*args, **kw)
        return wrapper
    

    五、偏函数

    1. functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(), 可以直接使用下面的代码创建一个新函数int2:
    2. 简单总结functools.partial作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
    >>> import functools
    >>> int2 = functools.partial(int, base=2)
    >>> int2('1000000')
    64
    >>> int2('1010101')
    85
    
    >>> int2('1000000', base=10)
    1000000
    
    作者:睿晞
    身处这个阶段的时候,一定要好好珍惜,这是我们唯一能做的,求学,钻研,为人,处事,交友……无一不是如此。
    劝君莫惜金缕衣,劝君惜取少年时。花开堪折直须折,莫待无花空折枝。
    曾有一个业界大牛说过这样一段话,送给大家:   “华人在计算机视觉领域的研究水平越来越高,这是非常振奋人心的事。我们中国错过了工业革命,错过了电气革命,信息革命也只是跟随状态。但人工智能的革命,我们跟世界上的领先国家是并肩往前跑的。能身处这个时代浪潮之中,做一番伟大的事业,经常激动的夜不能寐。”
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    SpringCloud------获取配置文件属性值
    SpringCloud------MyBatisPlus代码生成器的使用
    Hanoi问题 算法
    常见的时间复杂度按数量级排列
    Java 匿名类
    java内部类
    Java 接口和抽象类
    使用引用类型变量来访问所引用对象的属性和方法时,Java 虚拟机绑定规则
    Python import搜索的路径顺序
    php 多次导入文件导致 Cannot redeclare class
  • 原文地址:https://www.cnblogs.com/tsruixi/p/12577672.html
Copyright © 2020-2023  润新知