Fork me on GitHub

Python进阶

函数式编程

原则

写代码要遵循==开发封闭==原则,虽然这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:

封闭:已实现的功能代码块

开放:对扩展开发


内容

装饰器

1
2
3
4
5
6
7
8
9
10
def w1(func):
def inner():
# 验证1
# 验证2
# 验证3
return func()
return inner
@w1 # 相当于执行了 w1(f1())
def f1():
print('f1')

当写完这段代码后(函数未被执行、未被执行、未被执行),python解释器就会从上到下解释代码,步骤如下:

1
2
def w1(func):  ==>将w1函数加载到内存
@w1

没错,从表面上看解释器仅仅会解释这两句代码,因为函数在没有被调用之前其内部代码不会被执行。

从表面上看解释器着实会执行这两句,但是
@w1 这一句代码里却有大文章

@函数名
: 是python的一种语法糖

如上例 @w1内部会执行以下操作
: 执行w1函数,并将 @w1 下面的 函数 作为 w1 函数的参数
即:@w1 等价于 w1(f1)

所以,内部就会去执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def inner:
#验证
return f1() # func是参数,此时 func 等于 f1
return inner # 返回的 inner,inner代表的是函数,非执行函数
# 其实就是将原来的 f1 函数塞进另外一个函数中。

# 将执行完的 w1 函数返回值赋值给@w1下面的函数的函数名
# w1函数的返回值是:

def inner:
#验证
return 原来f1() # 此处的 f1 表示原来的f1函数
# 然后,将此返回值再重新赋值给 f1,即:

new_f1 = def inner:
#验证
return 原来f1()

如此一来, 即执行了验证的功能,又执行了原来 f 函数的内容,并将原 f1 函数返回值,
返回给业务调用着。

参数传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 # 一个参数:

def w1(func):
def inner(arg):
# 验证1
# 验证2
# 验证3
return func(arg)
return inner
@w1
def f1(arg):
print('f1')

# 两个参数:

def w1(func):
def inner(arg1,arg2):
# 验证1
# 验证2
# 验证3
return func(arg1,arg2)
return inner
@w1
def f1(arg1,arg2):
print('f1')
问题: 装饰具有处理n个参数的函数的装饰器?
1
2
3
4
5
6
7
8
9
10
def w1(func):
def inner(*args,**kwargs):
# 验证1
# 验证2
# 验证3
return func(*args,**kwargs)
return inner
@w1
def f1(arg1,arg2,arg3):
print('f1')
问题:一个函数可以被多个装饰器装饰吗?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def w1(func):
def inner(*args,**kwargs):
# 验证1
# 验证2
# 验证3
return func(*args,**kwargs)
return inner
def w2(func):
def inner(*args,**kwargs):
# 验证1
# 验证2
# 验证3
return func(*args,**kwargs)
return inner
@w1
@w2
def f1(arg1,arg2,arg3):
print('f1')

Lambda函数(匿名函数)

  • 函数 : 最大程度地复用代码
    • 存在问题:若函数很小,很短,则会造成啰嗦,不方便阅读代码
  • lambda表达式
    • 一个表达式,函数体相对简单
    • 用法
      • 以lambda开头
      • 紧跟一定的参数
      • 参数后面用冒号和表达式主题分开
      • 只是一个表达式,没有return
    • 实例
      • stm = lambda x: 100 * x
      • stm(89) ==>8900

高阶函数

  • 定义 : 把函数作为参数使用的函数
  • 注意
    • 函数名称就是一个变量,即函数可以作为参数
  • 举例
    1
    2
    3
    4
    5
    def funA(n):
    return n * 100

    def funB(n):
    return funA(n) * 3

map函数

  • 对队列里的每个元素进行操作,即映射操作
  • map函数是系统提供的具有映射功能的函数,返回值是一个迭代对象,类型为map类
    • 注意:若用列表生成式得到的结果为空
  • 格式: map(func, *iterables)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# map举例
# 列表里的每个元素都乘以10

l1 = [ i for i in range(10)]
print(l1)
for i in li:
l2.append(i*10)

# 利用map来实现

def multen(n):
return n*10

l2 = map(multen, l1 ) # multen函数作为map函数的一个参数
for x in l2:
print(l2)

reduce函数

  • 作用: 归并,缩减 ,把可迭代对象最后归并为一个结果
  • 作为参数的函数要求:
    • 必须有两个参数
    • 必须有返回结果
  • 理解 :reduce([1,2,3]) == f(f(f(1),2),3) 即函数嵌套
  • 注意: reduce需要导入functools包
1
2
3
4
5
6
7
8
9
10
11
from functools import reduce

# 定义一个操作函数
# 加入操作函数来相加
def add(x,y):
return x + y

## 对列表[1,2,3]执行add的reduce操作

rst = reduce(add, [1,2,3])
print(rst)

filter 函数

过滤函数:对一组数据进行过滤,符合条件的数据会产生一个新的列表返回

与map函数比较

  • 相同 :
    • 都对列表的每个元素逐一进行操作
  • 不同 :

    • map 会生成一个跟原来数据相对应的新队列
    • filter 不一定,只有符合条件的才会进入新队列
  • filter函数写法

    • 利用给定函数进行判断
    • 返回值为一个布尔值
    • 调用格式 : filter(f,data) f 为过滤函数 data 为数据
1
2
3
4
5
6
7
8
9
10
# 案例 过滤偶数数据形成新列表

def isEven(a):
return a%2 ==0

list = [3,4,56,3,455,67,4,4]

rst = filter(isEven, l)

print([i for i in rst])
注意事项
  • 返回的filter内容是一个可迭代对象,需要逐个输出

排序

  • 把一个序列按照给定算法进行排序
  • key : 在排序前,对每一个元素进行 key 函数运算,可理解为按照 key 函数定义的逻辑进行排序 (key函数为排序函数的内嵌参数)
  • python2 python3 的差别较大
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 排序案例1

a = [21,5,7,456,45,66]
al = sorted(a, reverse=True)

print (al)

# 排序案例2

a = [4.-45.457.74.7.5]
# 按照数据的绝对值进行排序
# abs 为求绝对值的函数

al = sorted(a, key=abs, reverse=True)

print (al)
喜欢的可以对我打赏了哟~