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(
">>")

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM