#py函数式编程.py
#高阶函数map/reduce/filter/sorted、闭包函数/返回函数、匿名函数lamber、@装饰器decorator、偏函数functool.partial()
# =============================================================================
# #Py函数式编程.py
# #高阶函数、闭包函数/返回函数、匿名函数lamber、@装饰器decorator、偏函数functool.partial()
# #参考链接:https://www.liaoxuefeng.com/wiki/1016959663602400/1017328525009056
# =============================================================================
'''
深入:
一、import functools
#functools 模块中主要包含了一些函数装饰器和便捷的功能函数。
1、使用:@functools.wraps(func)
通过给decorator装饰器主函数内return返回的子函数 加上装饰器functools.wraps(func) 来纠正被此装饰器装饰过的func函数属性。
2、#使用:functools.partial()用来创建一个偏函数,即把一个函数的某些参数给固定住(即设置默认值),返回一个新函数。
#注意:偏函数实质上是一个 @装饰器 的原理,即在参数列表里追加进去 设置默认值的参数。
#如:int2('1000') 实则是运行的 int('1000',base=2)
#使用:
一、高阶函数(map/reduce/filter/sorted等)
高阶函数就是一个函数就可以接收另一个函数作为参数的函数。
1、map(func,*iterables) 将参数func函数 作用于 参数*iterables里的每一个内容,返回一个可迭代对象。
#注意 map(,)返回一个迭代器iterator,需要序列化才能输出。
`
2、reduce(func,*iterables,initial) 将参数func函数 作用于 参数序列上,并把结果继续和序列的下一个元素做累计计算。并最终返回值。
#注意 reduce(,) 直接返回累计作用的值。
3、filter(func,iters) 过滤序列序列。用参数func函数 过滤 参数iters序列,为True则留下,为False则丢弃。
#注意 filter(,)返回一个迭代器iterator,需要序列化才能输出。
4、sorted(iterable, key=None, reverse=False) 对参数iterable序列list进行排序,
#注意 参数key可用来接收一个函数来实现自定义的排序。
#注意 参数reverse为True则反向排序
二、返回函数(闭包)
闭包函数
#高阶函数除了可以接受函数作为参数外,还可以把函数作为 结果值返回。
#闭包 即在 外部函数中 又定义了 内部函数,并且,内部函数 可以引用 外部函数 的参数和局部变量。
#当 外部函数 返回 内部函数 时,相关参数和变量都保存在返回的函数中,这种闭包程序结构拥有极大的威力,称谓“闭包”。
#参考网址:https://blog.csdn.net/sc_lilei/article/details/80464645
1、使用:通过获取主函数的魔法属性__closure__返回的值来确定主函数是否存在闭包。
#__closure__属性返回一个元组对象,包含了闭包引用的外部变量。
#对闭包主函数的__closure__属性迭代后通过cell_contents来输出闭包引用的外部变量
#如果主函数 没有return子函数,就不存在闭包,主函数不存在_closure__属性,返回None
#如果主函数 return的子函数不引用外部变量,也就不存在闭包,主函数的__closure__属性同样返回None。
2、注意:闭包函数中的return返回内容指向(return返回子函数名称 而不是调用函数)、函数作用域。
3、注意:闭包时牢记一点:返回函数(子函数、内部函数)不要引用任何 循环变量,或者后续会发生变化的变量。
#如果子函数一定要引用循环变量,方法是再创建一个函数。
#用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:
三、匿名函数lambda
#关键字lambda表示匿名函数,lambda x : x*x,冒号前面表示函数参数,冒号后面表达式表示函数内容
1、#使用:匿名函数可以赋值变量,lambda也是一个函数对象,也可以赋值给变量,然后通过变量来调用匿名函数。
2、#使用:匿名函数可以作为返回值返回,如在函数定义里最后return lambda :x*x + y*y
#注意:匿名函数作为返回值返回,等同于return子函数,就是一个闭包函数。
3、#注意:匿名函数有个限制:只能有一个表达式,不用填写return,返回值就是该表达式的结果
四、装饰器@(decorator装饰器 = 高阶函数 + 闭包函数)
装饰器本质上是接受一个函数作为参数(高阶函数行为),并返回一个函数(闭包函数行为)。
返回函数即子函数 中定义添加内容后 再返回主函数的参数函数。
从而实现不修改 参数函数的基础上 在代码运行期间动态增加功能的方式。
1、#使用:functools.wraps(func)装饰器
#注意:装饰器装饰过的函数的原属性已经改变,因为装饰器内部是闭包主函数return返回了子函数。
#解决办法是 通过给decorator装饰器主函数内return返回的子函数 加上装饰器functools.wraps(func) 来纠正被此装饰器装饰过的func函数属性。
2、#深入:import functools
#functools 模块中主要包含了一些函数装饰器和便捷的功能函数。
2.1、使用:@functools.wraps(func)
通过给decorator装饰器主函数内return返回的子函数 加上装饰器functools.wraps(func) 来纠正被此装饰器装饰过的func函数属性。
五、偏函数functools.partial()
#functools 模块中主要包含了一些函数装饰器和便捷的功能函数。其中一个就是偏函数(Partial function)。
#偏函数可以通过设定参数的默认值,从而降低函数调用的难度。
1、#使用:functools.partial()用来创建一个偏函数,即把一个函数的某些参数给固定住(即设置默认值),返回一个新函数。
2、#注意:偏函数实质上是一个 @装饰器 的原理,即在参数列表里追加进去 设置默认值的参数。
#如:int2('1000') 实则是运行的 int('1000',base=2)
'''
'''
函数式编程就是一种抽象程度很高的编程范式。
函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。
函数就是面向过程的程序设计的基本单元。
纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。
而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。
函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
Python允许使用变量,因此,Python不是纯函数式编程语言。
'''
#################### 高阶函数
#高阶函数
#高阶函数就是一个函数就可以接收另一个函数作为参数的函数。
#一个函数就可以接收另一个函数作为 参数,这种函数就称之为高阶函数。
def add(x,y,fun):
return fun(x)+fun(y)
print(add(-5,6,abs))
##########
#使用 map(func,*iterables) 将参数func函数 作用于 参数*iterables里的每一个内容,返回一个可迭代对象。
#注意 map(,)函数返回的是一个迭代器iterato,可迭代对象,需要list获取序列化才能输出。
help(map)
type(map)
def f(x):
return x*x
r=map(f,[1,2,3,4,5,6,7,8,9])
print(list(r)) #注意 map(,)函数返回的是一个可迭代对象,需要list获取序列化才能输出。
#通过map(,)函数将int内容批量转换成str内容
list(map(str,[1,2,3,4,5,6,7,8,9]))
##########
#使用 reduce(func,*iterables,initial) 将参数func函数 作用于 参数序列上,并把结果继续和序列的下一个元素做累计计算。并最终返回值。
#注意 reduce(,) 直接返回累计作用的值。
#参数: func指定参数,iterables指定作用序列,initial指定初始化的序列值。
#注意:如果传入了 initial 参数值, 那么首先传的就不是 iterables 的第一个和第二个元素,而是 initial值 和 iterables的第一个元素
from functools import reduce
help(reduce)
def add(x,y):
return x+y
reduce(add,[1,3,5,7,9]) #注意 reduce(,)函数返回一个累计后的值。
#####
#示例1:
#如果考虑到字符串str也是一个序列,可作为reduce的参数2,则配合map(),就可以写出把str转换为int的函数
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] #注意参数s需要是一个str类型 来 对应字典的键明key
print(reduce(fn,map(char2num,'13579'))) #将字符串'13579'作为一个可迭代的类型参数。
#####
#示例2
#使用匿名函数lambda来简写示例1
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))
str2int('12580')
##########
#使用 filter(func,iters) 过滤序列序列。用参数func函数 过滤 参数iters序列,为True则留下,为False则丢弃。
#注意 filter(,)返回一个迭代器iterator,需要序列化才能输出。
#和map()类似,filter()也接收一个函数和一个序列。
#不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
help(filter)
#示例在一个list中,删掉偶数,值保留奇数:
def is_odd(n):
return n%2 == 1 #符号 %求余,//取整。
print(list(filter(is_odd,[1,2,3,4,6,7,8,9])))
#示例把一个序列中的空字符串删掉:
def not_empty(s):
return s and s.strip() #.strip()方法用于移除字符串头尾指定的字符(默认移除空格或换行符,注意只能删除开头和结尾)
print(list(filter(not_empty,['A','','B',None,'c',' '])))
#####
#示例用fielter求素数。(素数:一个正整数,如果只有1和它本身两个因数,则叫做素数,也叫做质数。)
#计算素数的一个方法是埃氏筛法,它的算法理解起来非常简单:
#首先,列出从2开始的所有自然数,构造一个序列:2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...
#取序列的第一个数2,它一定是素数,然后用2把序列的2的倍数筛掉:3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...
#取新序列的第一个数3,它一定是素数,然后用3把序列的3的倍数筛掉:5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...
#取新序列的第一个数5,然后用5把序列的5的倍数筛掉:7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...
#不断筛下去,就可以得到所有的素数。
def _odd_iter():
"""先构造一个从3开始的奇数序列,
注意 这是一个生成器,并且是一个无限序列的生成器。
"""
n=1
while True:
n=n+2
yield n
def _not_divisible(n):
"""然后定义一个筛选函数"""
return lambda x: x%n > 0
def prines():
"""最后定义一个生成器,不断返回下一个素数
这个生成器先返回第一个素数2,然后,利用filter()过滤函数不断产生筛选后的新的序列
"""
yield 2
it=_odd_iter() #初始化序列
while True:
n=next(it)
yield n
it= filter(_not_divisible(n),it) #构造新序列
"""由于prines()也是一个无限序列,所有调用时需要设置一个退出循环的条件"""
for n in prines():
if n<1000:
print(n)
else:
break
#生成器 yield
#包含yield的语句被称为 生成器。
#包含 基线条件 和 递归条件。 即最后一个条件处理 和 循环的条件处理。
a=_odd_iter()
print(a)
next(a)
##########
#使用 sorted(iterable, key=None, reverse=False) 对参数iterable序列list进行排序,
#注意 参数key可用来接收一个函数来实现自定义的排序。
#注意 参数reverse为True则反向排序
#示例 按绝对值大小排序
"""key参数指定的函数将作用于每一个元素上,并根据key函数返回的结果进行排序"""
sorted([36,5,-12,9,-21],key=abs)
sorted([36,5,-12,9,-21],key=abs,reverse=True)
help(sorted)
#################### 闭包函数(返回函数)
#使用 闭包函数
#高阶函数除了可以接受函数作为参数外,还可以把函数作为 结果值返回。
#闭包 即在 外部函数中 又定义了 内部函数,并且,内部函数 可以引用 外部函数 的参数和局部变量。
#当 外部函数 返回 内部函数 时,相关参数和变量都保存在返回的函数中,这种闭包程序结构拥有极大的威力,称谓“闭包”。
#参考网址:https://blog.csdn.net/sc_lilei/article/details/80464645
#注意:闭包函数中的return返回内容指向(return返回子函数名称 而不是调用函数)、函数作用域。
#注意:闭包时牢记一点:返回函数(子函数、内部函数)不要引用任何循环变量,或者后续会发生变化的变量。
#如果子函数一定要引用循环变量,方法是再创建一个函数。
#用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:
#使用:通过获取主函数的魔法属性__closure__返回的值来确定主函数是否存在闭包。
#__closure__属性返回一个元组对象,包含了闭包引用的外部变量。
#对闭包主函数的__closure__属性迭代后通过cell_contents来输出闭包引用的外部变量
#如果主函数 没有return子函数,就不存在闭包,主函数不存在_closure__属性,返回None
#如果主函数 return的子函数不引用外部变量,也就不存在闭包,主函数的__closure__属性同样返回None。
#一个可变参数的求和函数
def calc_sum(*args):
"""该函数 立刻返回求和的结果ax"""
ax=0
for n in args:
ax=ax+n
return ax
#一个返回求和函数名的函数
def lazy_sum(*args):
"""该函数 返回一个函数名(不带括号表示不运行函数),不立即求和,而是等到调用函数()时再进行求和;
闭包:
#闭包 即在 外部函数中 又定义了 内部函数,并且,内部函数 可以引用 外部函数 的参数和局部变量。
#当 外部函数 返回 内部函数 时,相关参数和变量都保存在返回的函数中,这种闭包程序结构拥有极大的威力,称谓“闭包”。
"""
def sum():
ax=0
for n in args:
ax=ax+n
return ax
""" 闭包return返回了子函数名,不是调用子函数()"""
return sum #注意这里是返回的 函数名,不带括号表示不运行函数。
f=lazy_sum(1,3,5,7,9) #相当于赋值给f,赋值内容为 主函数内return返回的子函数名
f() #这里才是进行了 主函数内return返回的子函数的调用,即立即求和计算结果。
#注意:闭包时牢记一点:返回函数(子函数、内部函数)不要引用任何循环变量,或者后续会发生变化的变量。
def count():
fs=[]
for i in range(1,4):
def f():
"""
#注意:闭包时牢记一点:返回函数(子函数、内部函数)不要引用任何循环变量,或者后续会发生变化的变量。
#如果子函数一定要引用循环变量,方法是再创建一个函数。
#用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:
如下内容即引用了循环变量,导致实例化后输出结果都为9
"""
return i*i
'''for循环,追加 函数名 进 fs空列表'''
fs.append(f)
return fs
f1,f2,f3=count() #等于 f1,f2,f3=[f, f, f]
f1() #等于运行 f() 实质子函数f()里i已经运行完毕为最后的 3 。
f2() #等于运行 f() 实质子函数f()里i已经运行完毕为最后的 3 。
f3() #等于运行 f() 实质子函数f()里i已经运行完毕为最后的 3 。
#注意:闭包时牢记一点:返回函数(子函数、内部函数)不要引用任何循环变量,或者后续会发生变化的变量。
#如果子函数一定要引用循环变量,方法是再创建一个函数。
#用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:
def count():
def f(j):
def g():
return j*j
return g
"""一个空列表fs,接下来准备append追加进如内容:内容为 函数名带绑定后的参数i 即 f(1)、f(2)、f(3)"""
fs=[]
for i in range(1,4):
fs.append(f(i))
return fs
f1,f2,f3=count() #这里实质是列表多重赋值,等于 f1,f2,f3=[f(1),f(2),f(3)]
f1()
f2()
f3()
count()
#继续加深对闭包的理解
_list = []
for i in range(3):
def func():
return i+1
func.__num__= i
""" 这里实则添加完毕以后的 _list内容为[func,func,func],但是每一个func的__num__不同"""
_list.append(func)
for f in _list:
print(f.__num__,
f()
)
#实际输出
#0 3
#1 3
#2 3
#通过主函数的参数判断 来return指定子函数。
def get_math_func(type) :
# 定义一个计算平方的局部函数
def square(n) :
return n * n
# 定义一个计算立方的局部函数
def cube(n) :
return n * n * n
# 定义一个计算阶乘的局部函数
def factorial(n) :
result = 1
for index in range(2 , n + 1):
result *= index
return result
# 返回局部函数
if type == "square" :
return square
if type == "cube" :
return cube
else:
return factorial
# 调用get_math_func(),程序返回一个嵌套函数
math_func = get_math_func("cube") # 得到cube函数
print(math_func(5)) # 输出125
math_func = get_math_func("square") # 得到square函数
print(math_func(5)) # 输出25
math_func = get_math_func("other") # 得到factorial函数
print(math_func(5)) # 输出120
##########
#使用:通过获取主函数的魔法属性__closure__返回的值来确定主函数是否存在闭包。
#__closure__属性返回一个元组对象,包含了闭包引用的外部变量。
#对闭包主函数的__closure__属性迭代后通过cell_contents来输出闭包引用的外部变量
#如果主函数 没有return子函数,就不存在闭包,主函数不存在_closure__属性,返回None
#如果主函数 return的子函数不引用外部变量,也就不存在闭包,主函数的__closure__属性同样返回None。
# NO.1
def line_conf1(a, b):
def line(x):
return a * x + b
return line
# NO.2
def line_conf2():
a = 1
b = 2
def line(x):
print(a * x + b)
return line
# NO.3
def _line_(a,b):
def line_c(c):
def line(x):
return a*(x**2)+b*x+c
return line
return line_c
L=line_conf2()
print(line_conf2().__closure__) #通过获取主函数的魔法属性__closure__返回的值来确定主函数是否存在闭包。
for i in line_conf2().__closure__:
print(i.cell_contents) #对闭包主函数的__closure__属性迭代后通过cell_contents来输出闭包引用的外部变量
#####
#闭包的实际应用1
def who(name):
def do(what):
print(name,'say:',what)
return do
lucy=who('lucy')
lucy('I want drink!')
#####
#闭包的实际应用
#闭包实现快速给不同项目记录日志:
import logging
def log_header(logger_name):
""" """
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s [%(name)s] %(levelname)s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
logger = logging.getLogger(logger_name)
def _logging(something,level):
""" 返回的数(子函数),通过判断参数2 来调用日志输出类型,输出内容为参数1 """
if level == 'debug':
logger.debug(something)
elif level == 'warning':
logger.warning(something)
elif level == 'error':
logger.error(something)
else:
""" 如果没有传入参数2日志级别,则手动引发异常"""
raise Exception("I dont know what you want to do?" )
return _logging
project_1_logging = log_header('project_1')
project_2_logging = log_header('project_2')
def project_1():
#多此一举加函数
project_1_logging('this is a debug info','debug')
project_1_logging('this is a warning info','warning')
project_1_logging('this is a error info','error')
def project_2():
#多此一举加函数
project_2_logging('this is a debug info','debug')
project_2_logging('this is a warning info','warning')
project_2_logging('this is a critical info','error')
project_1()
project_2()
#################### 匿名函数
#关键字lambdab表示匿名函数,lambda x : x*x,冒号前面表示函数参数,冒号后面表达式表示函数内容
#使用:匿名函数可以赋值变量,lambda也是一个函数对象,也可以赋值给变量,然后通过变量来调用匿名函数。
#使用:匿名函数可以赋值变量,lambda也是一个函数对象,也可以赋值给变量,然后通过变量来调用匿名函数。
#使用:匿名函数可以作为返回值返回,如在函数定义里最后return lambda :x*x + y*y
#注意:匿名函数作为返回值返回,等同于return子函数,就是一个闭包函数。
#注意:匿名函数有个限制:只能有一个表达式,不用填写return,返回值就是该表达式的结果
#可以使用 lambda匿名函数 结合 map高阶函数 来计算乘方
list(map(lambda x: x*x,[1,2,3,4,5,6,7,8,9]))
#使用:匿名函数可以赋值变量,lambda也是一个函数对象,也可以赋值给变量,然后通过变量来调用匿名函数。
f=lambda x: x*x
f(5)
f
#使用:匿名函数作为返回值返回,如在函数定义里最后return lambda :x*x + y*y
#注意:匿名函数作为返回值返回,等同于return子函数,就是一个闭包函数。
def build(x,y):
""" 匿名函数作为返回值返回,等同于return子函数,就是一个闭包函数
注意:闭包函数注意 return的返回指向是否存在()的调用形式"""
return lambda :x*x + y*y
b=build(5,10)
b()
#可以使用lambda匿名函数 结合 map高阶函数 来过滤偶数
list(filter(lambda n: n%2==1,range(1,21)))
################### 装饰器@(decorator装饰器 = 高阶函数 + 闭包函数)
#装饰器本质上是接受一个函数作为参数(高阶函数行为),并返回一个函数(闭包函数行为)。
#返回函数即子函数 中定义添加内容后 再返回主函数的参数函数。
#从而实现不修改 参数函数的基础上 在代码运行期间动态增加功能的方式。
#使用:functools.wraps(func)装饰器
#注意:装饰器装饰过的函数的原属性已经改变,因为装饰器内部是闭包主函数return返回了子函数。
#解决办法是 通过给decorator装饰器主函数内return返回的子函数 加上装饰器functools.wraps(func) 来纠正被此装饰器装饰过的func函数属性。
#深入:import functools 使用:@functools.wraps(func)
#####
#定义一个本身不需要传入参数的装饰器 打印日志的装饰器decorator
def log(func):
"""接收一个函数作为参数,称为高阶函数
返回子函数,称为闭包函数"""
def wrapper(*args,**kw):
"""返回主函数的参数函数,从而达到不修改参数函数的基础上 动态增加print功能"""
print('开始调用函数:%s()' %func.__name__)
"""动态增加print功能后,继续调用原函数()执行"""
return func(*args,**kw)
return wrapper
"""使用:@decorator放到 func函数定义前,相当于执行了 func=decorator(func),重新赋值定义了一个同名新函数"""
@log
def now():
print('2019/11/08')
now()
"""等同于不添加装饰器@log情况下的如下表示:"""
#log(now)()
#now=log(now)
#now()
#####
#定义一个本身需要传入参数的装饰 打印日志的装饰器
#使用:如果装饰器decorator本身需要传入参数,那就需要编写一个返回装饰器的高阶函数(即三层嵌套装饰器函数)。
def log(who):
def decorator(func):
def wrapper(*args,**kw):
print('%s开始调用函数:%s()' %(who,func.__name__))
return func(*args,**kw)
return wrapper
return decorator
@log('小王')
def now():
print('2019/11/09')
now()
"""等同于不添加#log('小王')的如下表示:"""
#log('小张')(now)()
#now=log('小张')(now)
#now()
#####
#使用:functools.wraps(func)装饰器
#注意:装饰器装饰过的函数的原属性已经改变,因为装饰器内部是闭包主函数return返回了子函数。
#解决办法是 通过给decorator装饰器主函数内return返回的子函数 加上装饰器functools.wraps(func) 来纠正被此装饰器装饰过的func函数属性。
#深入:import functools
#functools 模块中主要包含了一些函数装饰器和便捷的功能函数。
#2.1、使用:@functools.wraps(func)
#通过给decorator装饰器主函数内return返回的子函数 加上装饰器functools.wraps(func) 来纠正被此装饰器装饰过的func函数属性。
import functools
def log(func):
# @functools.wraps(func)
def wrapper(*args,**kw):
print('开始调用函数:%s()' %func.__name__)
return func(*args,**kw)
return wrapper
@log
def now():
print('2019/11/09')
now()
print(now.__name__)
#对比添加了 @functools.wraps(func) 装饰器之后的 now.__name__
import functools
def log(who):
def decorator(func):
"""使用:functools.wraps(func)装饰器
通过给decorator装饰器主函数内return返回的子函数 加上装饰器functools.wraps(func)
来纠正被此装饰器装饰过的func函数属性。
"""
@functools.wraps(func)
def wrapper(*args,**kw):
print('%s \n %s开始调用函数:%s' %('接下来使用了functools.wraps(func)技术',who,func.__name__))
return func(*args,**kw)
return wrapper
return decorator
@log('小刘')
def now():
print('2019/11/10')
now()
now.__name__
#################### 偏函数functools.partial()
#functools 模块中主要包含了一些函数装饰器和便捷的功能函数。其中一个就是偏函数(Partial function)。
#偏函数可以通过设定参数的默认值,从而降低函数调用的难度。
#使用:functools.partial()用来创建一个偏函数,即把一个函数的某些参数给固定住(即设置默认值),返回一个新函数。
#注意:偏函数实质上是一个 @装饰器 的原理,即在参数列表里追加进去 设置默认值的参数。
#如:int2('1000') 实则是运行的 int('1000',base=2)
#修改int()函数的默认base参数,来达到 N进制的转换。
int('1000', base=8) #八进制:十位数上表示*8、百位数上表示64(8*8)、千位数上表示512(8*8*8)
int('10000',base=2) #二进制:十位数上表示*2、百位数上表示4(2*2)、千位数上表示8(2*2*2)
#使用:functools.partial()用来创建一个偏函数,即把一个函数的某些参数给固定住(即设置默认值),返回一个新函数。
import functools
int2=functools.partial(int,base=2)
int2('1000')
#注意:偏函数实质上是一个 @装饰器 的原理,即在参数列表里追加进去 设置默认值的参数。
#如:int2('1000') 实则是运行的 int('1000',base=2)
max2=functools.partial(max,10)
max2(2,5,9) #max2(2,5,9) 实则是运行的max(2,5,9,10)
py函数式编程(高阶函数map/reduce/filter/sorted、闭包函数/返回函数、匿名函数lamber、@装饰器decorator、偏函数functool.partial())
最新推荐文章于 2021-10-20 12:08:39 发布