【语言工具】Python闭包,装饰器,生成器,偏函数,函数式编程,lamda,map,reduce,filter

时间:2021-03-21 18:31:37
边界效应函数:可以修改内部状态,或者是其他无法反应在输出上的变化的函数
闭包:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数+相关外部变量就被认为是闭包(closure)。

            例:函数f内嵌套函数sub_f,但是子函数fsub_f引用了外部函数f的变量。注意,若函数f返回值为sub_f,则多次返回会创建不同的函数。

           参考:http://www.jb51.net/article/86383.htm

            【语言工具】Python闭包,装饰器,生成器,偏函数,函数式编程,lamda,map,reduce,filter


装饰器:在闭包的基础上传递了一个函数(见下文func),然后覆盖原来函数的执行入口(nei_hanshu的参数canshu),以后调用这个函数(login)的时候,就可以额外实现一些功能了。一般在原函数的前,或者后增加功能,不改变原函数内部的功能。

目的:为了不修改原函数(login)的代码,也不修改其他调用这个函数的代码,就能实现功能的拓展(调用外部不同的func)。

适用性:当为一个函数前前后后增加功能时,

参考:http://www.jb51.net/article/65774.htm   http://www.jb51.net/article/134598.htm

【语言工具】Python闭包,装饰器,生成器,偏函数,函数式编程,lamda,map,reduce,filter

装饰器的另一种写法,语法糖,@zsq=(login=zsq(login)

【语言工具】Python闭包,装饰器,生成器,偏函数,函数式编程,lamda,map,reduce,filter

带参数的装饰器:

【语言工具】Python闭包,装饰器,生成器,偏函数,函数式编程,lamda,map,reduce,filter

【语言工具】Python闭包,装饰器,生成器,偏函数,函数式编程,lamda,map,reduce,filter

装饰器的嵌套:

【语言工具】Python闭包,装饰器,生成器,偏函数,函数式编程,lamda,map,reduce,filter

也就是从上到下的嵌套了。

同时为装饰多个函数功能,并一起工作

【语言工具】Python闭包,装饰器,生成器,偏函数,函数式编程,lamda,map,reduce,filter

注意:

1.函数的参数传递的其实是引用,而不是值。

2.函数名也是一个变量,所以可以重新赋值。

3.赋值操作的时候,先执行等号右边的。

4. @函数名 是python的一种语法糖。执行@后的函数f之前,将@下的函数low_f作为参数传入f内,在将f的返回值返回给下面的函数名low_f

Python不可变数据结构:tuple

  


函数式编程:
定义:
函数仅接受输入并产生输出,不包含任何能影响产生输出的内部状态。
特点:
  1. 避免边界效应:程序输出只依赖于输入,不使用在程序运行时可变的数据结构
  2. 任何情况下,使用相同的参数调用函数始终能产生同样的结果。
  3. 允许把函数本身作为参数传入另一个函数,还允许返回一个函数


纯函数式编程:完全没有边界效应,函数没有变量


对比:
面向对象编程:
包含内部状态(成员变量)和修改状态的函数(成员函数),程序运行过程中,可以不断的修改内部状态
函数式编程    :xx


高阶函数背景:
变量可以指向函数名:
函数结果返回给变量x = abs(-10); 函数名返回给变量:f = abs
函数名其实就是指向函数的变量:若将abs指向10,比如abs = 10,则abs(-10)会报错


高阶函数:
就可以接收另一个函数作为参数的函数,函数式编程就是指这种高度抽象的编程范式。如:
def add(x, y, f):
    return f(x) + f(y)
add(-5, 6, abs) 


高阶函数map函数:
迭代依次操作序列中每个元素,返回一个新的迭代器?接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次独立的作用到序列的每个元素,并把结果作为新的Iterator返回【独立作用每个元素】
案例:list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))


高阶函数reduce函数:迭代按函数的要求,操作序列中每个元素,返回一个操作结果,值?把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累计计算【结果依赖前后元素之间复用】

reduce第二个参数为任何实现了__iter__()方法的可迭代对象。如果不指定第三个参数,则第一次调用function将使用iterable的前两个元素作为参数。

from functools import reduce

案例:

reduce(add, [1, 3, 5, 7, 9])   #return 1+3  return 4+5 return 9+7 return 16+9

all(iterable) == reduce(lambda x, y: bool(x and y), iterable)
any(iterable) == reduce(lambda x, y: bool(x or y), iterable)
max(iterable[, args...][, key]) == reduce(lambda x, y: x if key(x) > key(y) else y, iterable_and_args)
min(iterable[, args...][, key]) == reduce(lambda x, y: x if key(x) < key(y) else y, iterable_and_args)
sum(iterable[, start]) == reduce(lambda x, y: x + y, iterable, start)



map()+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'))  # 注意string,list,dict,tuple都是可迭代对象


高阶函数filter()函数:用于过滤序列。filter接收一个函数和一个序列。与map不同,把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。【独立作用每个元素】且该操作位于最终处理完之后一起处理??迭代器指针会变化么?
案例:
def is_odd(n):
    return n % 2 == 1

list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))  # 删掉偶数,只保留奇数


zip(iterable1, iterable2, ...):函数返回一个列表,每个元素都是一个元组,包含(iterable1[n], iterable2[n], ...)

例如:zip([1, 2], [3, 4]) --> [(1, 3), (2, 4)] 
如果参数的长度不一致,将在最短的序列结束时结束;如果不提供参数,将返回空列表。



高阶函数sort(使用默认的数据或自定义映射函数处理后的数据,进行正序或者逆序排序):
  sorted()函数就可以对list进行排序:
  案例:sorted([36, 5, -12, 9, -21])
  可以接收一个key函数来实现自定义的排序,key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果(list或新list)进行排序:
  案例:sorted([36, 5, -12, 9, -21], key=abs)
             sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)
  进行反向排序,不必改动key函数,可以传入第三个参数reverse=True:
  案例:sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)


返回函数:即可以在函数f1中,定义函数sub_fx,根据需求参数,返回不同函数sub_fx。注意,每次调用f1,返回的是不同的实例。
def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum


>>> f1 = lazy_sum(1, 3, 5, 7, 9)
>>> f2 = lazy_sum(1, 3, 5, 7, 9)
>>> f1==f2


匿名函数:为了编写偶尔为之的、简单的、可预见不会被修改的匿名函数

lambda表达式定义一个匿名的函数,如果这个函数仅在编码的位置使用到,你可以现场定义、直接使用:

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

限制:就是只能有一个表达式,不用写return,返回值就是该表达式的结果。

优点:函数没有名字,不必担心函数名冲突;匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数。如 f = lambda x: x * x;也可以把匿名函数作为返回值返回;匿名函数常常结合map,reduce,fileter一起使用

案例:lst.sort(lambda o1, o2: o1.compareTo(o2)) # 输入o1,02, 输出冒号后面的操作的结果


生成器:

生成器就是一种迭代器。生成器拥有next方法并且行为与迭代器完全相同,这意味着生成器也可以用于Python的for循环中。

生成器可以挂起,所以是延迟计算的,在yield外面加while True无限循环并没有关系。

加入了yield的函数叫做生成器函数,第一次调用生成器的next方法时,生成器才开始执行生成器函数,,直到遇到yield时暂停执行(挂起),并且yield的参数将作为此次next方法的返回值;

【语言工具】Python闭包,装饰器,生成器,偏函数,函数式编程,lamda,map,reduce,filter

【语言工具】Python闭包,装饰器,生成器,偏函数,函数式编程,lamda,map,reduce,filter

【语言工具】Python闭包,装饰器,生成器,偏函数,函数式编程,lamda,map,reduce,filter

【语言工具】Python闭包,装饰器,生成器,偏函数,函数式编程,lamda,map,reduce,filter

http://www.jb51.net/article/68319.htm


偏函数

functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2

为避免每次传入base=2的写法,可将int(“123‘’,base=2)写作:

【语言工具】Python闭包,装饰器,生成器,偏函数,函数式编程,lamda,map,reduce,filter


functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。

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

【语言工具】Python闭包,装饰器,生成器,偏函数,函数式编程,lamda,map,reduce,filter