【笔记】Python学习(廖雪峰)笔记③——Python函数式编程

函数式编程 Functional Programming

特点:允许把函数本身作为参数传入另一个函数,还允许返回一个函数

Python:对函数式编程提供部分支持,由于Python允许使用变量,所以,Python不是纯函数式编程语言

高阶函数 Higher-order function

函数调用结果可以赋值给变量

变量可以指向函数,可以通过该变量来调用函数

函数名也是变量

传入函数

一个函数可以接收另一个函数作为参数,这样的函数就称为高阶函数

def add(x,y,f):
    # f 为函数名
    return f(x) + f(y)

map/reduce

map(function,Iterator)

map 将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回

将运算规则抽象化

def f(x):
    return x*x
L = [1,2,3,4,5,6,7,8,9,10]
r = map(f,L)
list(r)#结果r是一个Iterator,通过list()函数将整个序列都计算出来并返回一个list
reduce(function,Iterator)

function(parameter1 parameter2) 该函数需要接收两个参数

reduce 把结果和序列的下一个元素做累积计算(可以理解为不断嵌套?)

>>> from functools import reduce
>>> def fn(x, y):
...     return x * 10 + y

>>> def char2num(s):
...     digits = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
...     return digits[s]
...
>>> reduce(fn, map(char2num, '13579'))
#map函数通过将char2num函数应用到字符串'13579'上,将‘13579’变成int型 [1,3,5,7,9]
#reduce函数通过fn函数应用到[1,3,5,7,9]上,将[1,3,5,7,9]变成整数13579
13579

filter

filter(function,Iterator)

用途:filter把传入的函数依次作用于每个元素,然后根据返回值是True or False决定保留还是丢弃该元素

例子:埃式筛法,回数

sorted

sortrd(list,function)

用途:将function作用于每一个元素上,并根据function返回的结果进行排序,按照对应关系返回list相应的元素

Key:实现一个映射函数

例子:

#按照字母序排序(因为没有统一大小写的话,会按照ASCII码排序)
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)

#反向排序,参数reverse
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)

返回函数

函数作为函数值

高阶函数可以将函数作为结果值返回

闭包Closure

在函数A内部又定义了函数B,并且,内部函数B可以引用外部函数A的参数和局部变量,当A返回函数B时,相关参数和变量都保存在返回的函数中

· 闭包返回的函数并没有立即执行,直到调用才开始执行

def lazy_func():
    def func():
        pass
    return func
#得到返回的函数但并没有立即执行
f = lazy_func()
#调用f()才开始执行
f()

· 返回闭包时注意:返回函数不要引用任何循环变量,或者后续会发生变化的变量

· 如果一定要引用循环变量,方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论后续变量如何更改,已绑定到函数参数的值不变。[简单来说,就是在函数内部直接完成调用执行,而不是在外部调用执行,用参数进行绑定]

def count():
    def f(i):
        def g():
            return j*j
        return g
    fs = []
    for i in range(1,4):
        fs.append(f(i))
    return fs
nonlocal

在内部函数加入 nonlocal x 声明,加入声明之后,解释器将内部函数中的 x 看作外层函数的局部变量

why : 在内部函数直接对外部函数中的变量 赋值 ,解释器会将该变量视为内部函数的局部变量,加入声明后,可以解决该问题

匿名函数

lambda x : x * x

关键字 lambda 表示匿名函数,冒号前的x表示函数参数

匿名函数无需担心函数名冲突

匿名函数是一个函数对象,可以把匿名函数赋值给一个变量,再利用变量来调用该函数

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

def build(x,y):
    return lambda: x * x + y * y

装饰器Decorator

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

本质上,decorator就是一个返回函数的高阶函数

# 定义一个能打印日志的decorator
def log(func):
    def wrapper(*args,**kw):
        print('call %s():' % func._name_)
        return func(*args,**kw)
    return wrapper

# 借助python的 @ 语法,把decorator置于函数的定义处
@log
def now():
    print('2022/10/8')

# 调用now()函数,不仅会运行now()函数本身,还会在运行now()函数前运行log()
>>> now()
call now():
2022/10/8

理解 @log

@log
def now():
=
now = log(now)
# log()是一个装饰器,返回一个函数,所以,原来的now()函数仍然存在,只是现在同名的now变量指向了新的函数log(now)
# 因此此时调用 now() 将执行新函数,即log()函数中返回的wrapper()函数

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

# 自定义Log的文本内容
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('2022/10/8')
=
now = log('execute')(now)
# 执行(先执行log,再执行now)
>>> now()
execute now()
2022/10/8

经过decorator装饰之后的函数,其name发生变化(一般变成最内层的wrapper),因此需要把原始函数的 __name__ 等属性复制到 wrapper() 函数中,否则,有些依赖函数签名的代码执行就会出错

import functools

def log(func):
    # 在wrapper定义前,加入下面一行内容,即可将属性复制
    @functools.wraps(func)
    def wrapper(*args,**kw):
        print('call %s():' % func.__name__)
        return func(*args,**kw)
    return wrapper

偏函数 Partial Function

functools.partial 帮助创建偏函数

import functools
# int('12345') 默认将12345转换成十进制形式的数字
# base参数可以做N进制的转换

# 用函数表达
def int2(x,base=2):
    return int(x,base)

# 使用functools.partial表达
int2 = functools.partial(int,base=2)

functools.partial 的作用是:把一个函数的某些参数固定,返回一个新的函数

创建偏函数时,可以接收 函数对象 *args **kw 这三个参数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值