Python入门篇-functools
Python入门篇-functools
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.reduce方法
reduce方法,顾名思义就是减少
reduce(function,sequence[,initial])->value
可迭代对象不能位空;初始值没提供就在可迭代对象中取一个元素
1 #!/usr/bin/env python 2 #_*_conding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie 5 6 7 from functools import reduce 8 9 10 print(reduce(lambda x,y:x*y,range(1,6))) #我们可以用来计算5的阶乘 11 print(reduce(lambda x,y:x*y,range(1,6),100)) #当然,我们也可以指定函数的起始值,这个起始值会直接赋值给x变量,如果没有指定则会使用序列的第一个数字来赋初值。 12 13 nums = [6,9,4,2,4,10,5,9,6,9] 14 print(nums) 15 print(sum(nums)) 16 print(reduce(lambda x,y:x+y,nums)) 17 18 19 20 #以上代码输出结果如下: 21 120 22 12000 23 [6, 9, 4, 2, 4, 10, 5, 9, 6, 9] 24 64 25 64
二.partial方法
1>.partial概述
偏函数,把函数部分的参数固定下来,相当于为部分的参数添加了一个固定的默认值,形成一个新的函数并返回
从partial生成的新函数,是对原函数的封装
2>.partial方法举例
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 8 import functools,inspect 9 10 def add(x, y, *args) -> int: 11 print("add args:{}".format(args)) 12 return x + y 13 14 newadd = functools.partial(add, y=5) 15 16 print(inspect.signature(add)) 17 print(newadd(7)) 18 print(newadd(10, y=20)) 19 print(newadd(y=10, x=6)) 20 print(inspect.signature(newadd)) 21 22 23 24 #以上代码执行结果如下: 25 (x, y, *args) -> int 26 add args:() 27 12 28 add args:() 29 30 30 add args:() 31 16 32 (x, *, y=5) -> int
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 8 import functools,inspect 9 10 def add(x, y, *args) -> int: 11 print("add args:{}".format(args)) 12 return x + y 13 14 newadd = functools.partial(add, 1,3,6,5) 15 print(newadd(7)) 16 print(newadd(7, 10)) 17 print(newadd()) 18 print(inspect.signature(add)) 19 print(inspect.signature(newadd)) 20 21 22 23 #以上代码执行结果如下: 24 add args:(6, 5, 7) 25 4 26 add args:(6, 5, 7, 10) 27 4 28 add args:(6, 5) 29 4 30 (x, y, *args) -> int 31 (*args) -> int
3>.partial函数本质
def partial(func, *args, **keywords): def newfunc(*fargs, **fkeywords): # 包装函数 newkeywords = keywords.copy() newkeywords.update(fkeywords) return func(*(args + fargs), **newkeywords) newfunc.func = func # 保留原函数 newfunc.args = args # 保留原函数的位置参数 newfunc.keywords = keywords # 保留原函数的关键字参数参数 return newfunc
def add(x,y): return x+y
foo = partial(add,4) foo(5)
二.lru_cache方法
1>.lru_cache概述
@functools.lru_cache(maxsize=128, typed=False) Least-recently-used装饰器。lru,最近最少使用。cache缓存 如果maxsize设置为None,则禁用LRU功能,并且缓存可以无限制增长。当maxsize是二的幂时,LRU功能执行得最好 如果typed设置为True,则不同类型的函数参数将单独缓存。例如,f(3)和f(3.0)将被视为具有不同结果的不同调用
2>. lru_cache举例
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 8 import functools 9 import time 10 11 @functools.lru_cache() 12 def add(x, y, z=3): 13 time.sleep(z) 14 return x + y 15 16 print(add(4, 5)) 17 print(add(4.0, 5)) 18 print(add(4, 6)) 19 print(add(4, 6, 3)) 20 print(add(3, 2)) 21 print(add(2, y=3)) 22 print(add(x=40, y=60)) 23 print(add(y=60, x=40))
3>.lru_cache装饰器
通过一个字典缓存被装饰函数的调用和返回值 key是什么?分析代码看看 functools._make_key((4,6),{'z':3},False) functools._make_key((4,6,3),{},False) functools._make_key(tuple(),{'z':3,'x':4,'y':6},False) functools._make_key(tuple(),{'z':3,'x':4,'y':6}, True)
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 8 import functools 9 10 @functools.lru_cache() # maxsize=None 11 def fib(n): 12 if n < 3: 13 return n 14 return fib(n-1) + fib(n-2) 15 16 print([fib(x) for x in range(35)]) 17 18 19 20 21 #以上代码执行结果如下: 22 [0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465]
4>.lru_cache装饰器应用
使用前提 同样的函数参数一定得到同样的结果 函数执行时间很长,且要多次执行
本质是函数调用的参数=>返回值
缺点 不支持缓存过期,key无法过期、失效 不支持清除操作 不支持分布式,是一个单机的缓存
适用场景,单机上需要空间换时间的地方,可以用缓存来将计算变成快速的查询
三.装饰器应用练习
1>.实现一个cache装饰器,实现可过期被清除的功能
简化设计,函数的形参定义不包含可变位置参数、可变关键词参数和keyword-only参数
可以不考虑缓存满了之后的换出问题
2>.写一个命令分发器
程序员可以方便的注册函数到某一个命令,用户输入命令时,路由到注册的函数
如果此命令没有对应的注册函数,执行默认函数
用户输入用input(">>")
本文来自博客园,作者:尹正杰,转载请注明原文链接:https://www.cnblogs.com/yinzhengjie/p/10976621.html,个人微信: "JasonYin2020"(添加时请备注来源及意图备注,有偿付费)
当你的才华还撑不起你的野心的时候,你就应该静下心来学习。当你的能力还驾驭不了你的目标的时候,你就应该沉下心来历练。问问自己,想要怎样的人生。