• 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
    partial方法举例

    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(
    ">>")
  • 相关阅读:
    Lua中如何实现类似gdb的断点调试—06断点行号检查与自动修正
    211. 添加与搜索单词 数据结构设计 (JAVA)
    SuperSocket 1.5 stable发布
    SuperWebSocket发布0.1版本
    无需等待,SuperSocket 1.4 SP1 发布了!
    SuperSocket 1.5 文档列表
    SuperSocket 1.4 SP2 发布了!
    imx6ull spiimx.c 驱动接收导致内存问题
    nacos下载、安装、使用,SpringCloud、SpringBoot、SpringCloudAlibaba版本匹配、openfeign、loadbalancer、nacos配置中心
    idea配置显示Run Dashboard,引入自定义jar包
  • 原文地址:https://www.cnblogs.com/yinzhengjie/p/10976621.html
Copyright © 2020-2023  润新知