Python函数式编程

2020-04-10  本文已影响0人  夏海峰

计算机(Computer)计算(Compute)这两个概念区分:在计算机的层次上,CPU执行的是加减乘除的指令代码,以及各种条件判断和跳转指令,所以,汇编语言是最贴近计算机的语言。而计算则指数学意义上的计算,越是抽象的计算,离计算机硬件越远。对应到编程语言,就是越低级的语言,越贴近计算机,抽象程度低,执行效率高,比如C语言;越高级的语言,越贴近计算,抽象程度高,执行效率低,比如Lisp语言。

函数式编程(Functional Programming):把大段代码拆解成函数,通过一层一层地调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数是面向过程的程序设计的基本单元。而函数式编程虽然也可以归结到面向过程的程序设计,但其思想更接近数学计算。

函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用。函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

1、高阶函数(函数作为参数)

(1)变量可以指向函数

abs(-10)   # 这是函数调用
f1 = abs   # 把函数本身赋值给一个变量
res1 = f1(-100)   # 100
print('res1', res1)

(2)函数名也是变量

abs(-10)  # 10
abs = print
abs(-10)  # -10
abs = 1
abs(-10)  # TypeError: 'int' object is not callable

(3)高阶函数

def add(x, y, fn):
    return fn(x) + fn(y)
res2 = add(-5, 6, abs)
print('res2', res2)

(4)高阶函数 map()

def square(x):
    return x*x
res3 = map(square, [1,2,3,4,5,6,7,8,9,10])
print('列表元素求平方:', list(res3))  
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
def money(num):
    return '¥'+str(num)
res4 = map(money, [1.9, 9.9, 19.9, 29.9, 39.9])
print('列表元素字符串处理:', list(res4))
# ['¥1.9', '¥9.9', '¥19.9', '¥29.9', '¥39.9']

(5)高阶函数 reduce()

from functools import reduce

def sum(x, y):
    return x + y
res5 = reduce(sum, [1, 2, 3, 4, 5])
print('[1, 2, 3, 4, 5]求和:', res5)  # 15

def deci(x, y):
    return x*10 + y
res6 = reduce(deci, [1, 2, 3, 4, 5, 0, 0])
print('res6', res6)  # 1234500

(6)高阶函数 filter()

def is_odd(n):
    return n % 2 == 1
res7 = filter(is_odd, [1,2,4,5,6,9,10,15])
print('去除列表中的偶数:', list(res7))  # [1, 5, 9, 15]
def not_empty(s):
    return s and s.strip()
res8 = filter(not_empty, ['A','','B','','','C'])
print('去除空串元素:', list(res8)) # ['A', 'B', 'C']

(7)高阶函数 sorted()

res9 = sorted([36, 5, -12, 9, -20])
print('sorted排序:', res9) # [-20, -12, 5, 9, 36]
res10 = sorted([36, 5, -12, 9, -20], key=abs)
print('sorted排序:', res10) # [5, 9, -12, -20, 36]
res11 = sorted(['bob', 'about', 'Zoo', 'Credit'])
print('默认ASCII的大小比较排序:', res11)
# ['Credit', 'Zoo', 'about', 'bob']
res12 = sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)
print('忽略大小写的排序:', res12)
# ['about', 'bob', 'Credit', 'Zoo']
res13 = sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
print('忽略大小写、反向排序:', res13)
# ['Zoo', 'Credit', 'bob', 'about']

2、高阶函数(函数作为返回值)

(1)函数作为返回值

def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax += n
        return ax
    return sum

f1 = lazy_sum(1,2,3,4,5)
res1 = f1()
print('1,2,3,4,5求和的结果是:', res1) # 15

(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', f1())  # 9
print('调用f2', f2())  # 9
print('调用f3', f3())  # 9

3、匿名函数(lambda 关键字)

res = map(lambda x: x*x, [1,2,3,4,5,6])
print('res', list(res)) # [1, 4, 9, 16, 25, 36]
f = lambda x: x*x
print('5的平方:', f(5))  # 25
def build(x,y):
    return lambda : x*x + y*y
print('3和4的平方和:', build(3,4)())  # 25

4、装饰器(函数修饰)

(1)函数对象的 __name__ 属性

def now():
    print('执行了')
f = now
now()  # 执行了
f()  # 执行了
print('__name__ ', now.__name__)  # 'now'
print('__name__ ', f.__name__)  # 'now'

(2)装饰器

import functools
def log(fn):
    @functools.wraps(fn)  # 解决被装饰器修饰后的函数__name__发生变化的问题。
    def wrapper(*args, **kw):
        print('日志打印:call %s()' % fn.__name__)
        return fn(*args, **kw)
    return wrapper
@log
def now():
    print('函数打印:2020-04-10')

now()
# 日志打印:call now()
# 函数打印:2020-04-10
print('now的__name__', now.__name__) # 'now'

(3)给装饰器传入参数

import functools
def log2(text):
    def decorator(fn):
        @functools.wraps(fn)  # 解决被装饰器修饰后的函数__name__发生变化的问题。
        def wrapper(*args, **kw):
            print('日志打印:%s %s()' %(text, fn.__name__))
            return fn(*args, **kw)
        return wrapper
    return decorator
@log2('自定义日志内容')
def now2():
    print('函数打印:2020-04-10')

now2()
# 日志打印:自定义日志内容 now2()
# 函数打印:2020-04-10
print('now2的__name__', now2.__name__) # 'now2'

5、偏函数(functools.partial)

import functools
int2 = functools.partial(int, base=2)
print('转成十进制', int2('1000000'))  # 64
print('转成十进制', int2('1010101'))  # 85

print('转成十进制', int2('1010101', base=10))  # 1010101
def int3(x, base=2):
    # int() 可以给第二个参数base,用于指定按N进制进行转化
    return int(x, base)
print('转成十进制', int3('1000000'))  # 64
print('转成十进制', int3('1010101'))  # 85

print('转成十进制', int3('1010101', base=10))  # 1010101

参考资源:
1、廖雪峰Python教程
2、Python官方文档


END!!!

上一篇 下一篇

猜你喜欢

热点阅读