zoukankan      html  css  js  c++  java
  • Python函数式编程

    函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。
    越低级的语言,越贴近计算机,抽象程度低,执行效率高;越高级的语言,越贴近计算,抽象程度高,执行效率低。
    函数式编程就是一种抽象程度很高的编程范式。
    函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!

    1. 高阶函数

    函数本身可以赋值给变量,即变量可以指向函数。如果一个变量指向了一个函数,可以通过该变量来调用这个函数。函数名其实就是指向函数的变量。
    一个函数接收另一个函数作为参数,这种函数就称之为高阶函数

    >>> def add(x, y, f):
            return f(x) + f(y)
    
    >>> print(add(-5, 6, abs)) # abs为Python内置的求绝对值的函数
    11
    

    编写高阶函数,就是让函数的参数能够接收别的函数。

    1.1 map

    >>> def f(x):
            return x * x
    
    >>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) # map(function, Iterable)
    >>> list(r)
    [1, 4, 9, 16, 25, 36, 49, 64, 81]
    

    map()接收两个参数,第一个是函数,第二个是Iterable
    map()将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。

    1.2 reduce

    reduce把函数作用在序列上,这个函数必须接收两个参数,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
    
    # 把字符串转化为数字
    from functools import reduce
    
    DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
    
    def str2int(s):
        def fn(x, y):
            return x * 10 + y
        def char2num(s):
            return DIGITS[s]
        return reduce(fn, map(char2num, s))
    	
    
    >>> from test import str2int
    >>> str2int('13579')
    13579
    
    from functools import reduce
    
    DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
    
    def char2num(s):
        return DIGITS[s]
    
    def str2int(s):
        return reduce(lambda x, y: x * 10 + y, map(char2num, s)) # 使用lambda函数简化
    
    

    lambda x, y: x * 10 + y就是lambda函数。

    1.3 filter

    Python内建的filter()函数用于过滤序列。
    filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

    >>> def is_odd(n):
    	return n % 2 == 1
    
    >>> list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
    [1, 5, 9, 15]
    

    注意到filter()函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list

    1.4 sorted

    Python内置的sorted()函数就可以对list进行排序。

    >>> 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']
    

    默认情况下,对字符串排序,是按照ASCII的大小比较的。

    2. 返回函数

    def lazy_sum(*args):
        def sum():
            ax = 0
            for n in args:
                ax = ax + n
            return ax
        return sum
    	
    
    >>> from test import lazy_sum
    >>> f = lazy_sum(1,3,5,7,9)
    >>> f
    <function lazy_sum.<locals>.sum at 0x0093C6F0>
    >>> f()
    25
    

    3. 匿名函数

    >>> list(map(lambda x: x * x, [1, 2, 3, 4, 5]))
    [1, 4, 9, 16, 25]
    

    关键字lambda表示匿名函数,冒号前面的x表示函数参数。
    匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。

    4. 装饰器

    由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数。
    函数对象有一个__name__属性,可以拿到函数的名字。

    >>> def hello():
            print('Hello!')
    
    	
    >>> h = hello
    >>> h()
    Hello!
    >>> h.__name__
    'hello'
    >>> hello.__name__
    'hello'
    

    在代码运行期间动态增加功能的方式,称之为装饰器

    def log(func):
        def wrapper(*args, **kw):
            print('call %s():' % func.__name__)
            return func(*args, **kw)
        return wrapper
    """
    import functools
    
    def log(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('call %s():' % func.__name__)
            return func(*args, **kw)
        return wrapper
    """
    	
    @log
    def now():
        print('2019-4-7')
    
    
    now()
    
    # call now():
    # 2019-4-7
    

    如果装饰器本身需要传入参数,那就需要编写一个返回装饰器的高阶函数。

    def log(text):
        def decorator(func):
            def wrapper(*args, **kw):
                print('%s %s():' % (text, func.__name__))
                return func(*args, **kw)
            return wrapper
        return decorator
    """
    import functools
    
    def log(text):
        def decorator(func):
            @functools.wraps(func)
            def wrapper(*args, **kw):
                print('%s %s():' % (text, func.__name__))
                return func(*args, **kw)
            return wrapper
        return decorator
    """	
    	
    @log('execute')
    def now():
        print('2019-4-7')
    	
    
    now()
    
    # execute now():
    # 2019-4-7
    

    5. 偏函数

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

    import functools
    
    int2 = functools.partial(int, base=2)
    print(int2('1000000')) # int('1000000', base=2)
    
    """
    def int2(x, base=2):
        return int(x, base)
    	
    """
    
    # 64
    

    参考资料:

  • 相关阅读:
    OpenCV程序在生产环境中运行
    C#调用C++导出(dllexport)方法
    IIS7.5 GZip配置
    wcf学习笔记--初识wcf
    Greenplum installation guide
    Cloudera 5.8.2 Installation guide
    WPF DataGrid 合并单元格
    wpf DataGrid CheckBox列全选
    WPF button 圆角制作
    WPF passwordbox 圆角制作
  • 原文地址:https://www.cnblogs.com/gzhjj/p/10665860.html
Copyright © 2011-2022 走看看