高階函數和裝飾器

高階函數的定義:
函數也能夠是對象,或者能夠調用的對象
函數能夠做爲普通變量,參數,數值等等
     數學概念: y =g(f(x))
     高階函數應該是一個至少知足下面一個條件的函數
          接受一個或多個函數做爲參數
          輸出一個函數
 
本身寫一個排序的函數:
def sort(iterable):
lst = []
for i in iterable:
     for j,m in enumerate(lst):
if i > m:
                lst.insert(j,i)
                break
     else:
          lst.append(i)
return lst
 
lst1=[9,5,4,7,6,5,1]
print(sort(lst1))
本身實現sort排序之flag版:
 
def sort(iterable,reverse=Flase):         #(reverse默認爲假,非False即爲真)
     lst=[]
     for i in iterable:
          for j,m in enumerate lst:
               flag=i>m if reverse else i<m                    #(客戶可在函數後增長 參數進行判斷升降序)
               if flag:
                    lst.insert(j,i)
                    break
          else:
               lst.append(i)
     return lst
 
lst1=[8,7,6,2,1,4,9]
print(sort(lst1,reverse的參數))  
本身實現sort排序之函數版(進階):
def sort(iterable,key=lambda a,b:a<b):     #定義升降序的默認值
  lst = []
  for i in iterable:
             for j, m in enumerate(lst):
                 flag=key(i,m)                 #返回布爾值(True,False)
                 if flag:
                     lst.insert(j, i)
                     break
             else:
                 lst.append(i)
  return lst
 
lst1 = [8, 7, 6, 2, 1, 4, 9]
print(sort(lst1,lambda a,b:a>b))
filter(function,iterable)
     過濾可迭代對象的元素。返回一個迭代器
     function 一個具備一個參數的函數,返回bool值
     舉例:
list(filter(lambda x : x%3,range(50)))
     就會過濾出50之內全部的能被3整除的數字
 
map(function,*iterbale)-->object
     對多個可迭代對象的元素按照指定的函數進行映射,返回一個迭代器
 
柯里化函數
柯里化的定義:
將原來接收兩個參數的函數變成新的接收一個參數的函數的過程,新的函數返回一個以原有第二個參數爲參數的函數
      Z=f(x,y)轉換成Z=f(x)(y)的方式    
經過嵌套函數就能夠把函數轉換成柯里化函數
def nums(x):
     def nums1(y):
          nonlocal x
          x+=y
          return x
     return nums1
foo = nums(5)
foo(6)
 
工做中,業務代碼只執行特定的業務,而其餘的則須要在裝飾器的幫助下實現加強語句
例如一個函數爲:
def sum(x,y):
      value=x+y
      return value
這個代碼只執行一個計算的程序,我稱之其爲業務代碼,若是我想在其上下添加‘語句塊’可是又不想入侵這個業務代碼,就須要利用到裝飾器了
def coat(key):
     def pants(x,y):
          print('wow,you look so great')
          fn=key(x,y)
          print('i love it')
          return fn
     return pants
@coat          #sum=coat(sum)
def sum(x,y):
     value=x+y
     return value
這就是一個簡單的裝飾器,在不入侵業務代碼的同時,也能夠對其進行加強,當讓遠不止打印幾句話這種簡單用法,能夠添加 時間,計數等等
不適用裝飾器的弊端:
打印語句的耦合性過高
邏輯運算屬於業務功能,而輸出信息的功能,屬於非業務功能代碼,不能出如今 務語法中
 
作到了業務功能分離,可是fn的函數調用傳參是個問題
def add(x,y):
     return x+y
def logger(fn):
     print('begin')
     x= fn(4,5)
     print('end')
     return x
 
print(logger(add)) 
 
使用裝飾器解決:
def logger(fn):
     def _logger(*args)
          print('begin')
          x= fn(*args)
          print('end')
          return x
@logger               #add=logger(add)
def add(x,y):
     return x+y
 
add(4,5)
輸出結果爲 
begin
end
9
這段代碼在不入侵業務代碼的同時,也加入了想要的內容,這種方法就叫作裝飾器
無參裝飾器
     它是一個函數
     函數做爲它的形參
     返回值也是一個函數
     使用@函數引用 方式,簡化代碼
 
一些簡單的無參裝飾器代碼:
import datetime
import time
 
def looger(fn):
         def warp(*args,**kwargs):
             # 加強功能
             print('args={},kwargs={}'.format(args,kwargs))      #聲明傳進來的是什麼東西
             start = datetime.datetime.now()
             ret = fn(*args,**kwargs)
             end = datetime.datetime.now() - start
             print('founc{} took {}s.'.format(warp.__name__,end.total_seconds()))     #打印函數執行時長
   return ret
         return warp
 
def add(x,y):
       print('===call add=========')
       time.sleep(2)
       return x + y
 
print(add(5,6))
 
代碼2(差異小):
import datetime
import time
def logger(new):
         def warp(*args,**kwargs):
             print('args={} kwargs={}.'.format(args,kwargs))
             start=datetime.datetime.now()
             ret = new(*args,**kwargs)
             times=datetime.datetime.now() - start
             print('func {} need {}s.'.format(warp.__name__,times))
             return ret
  return warp
 
@logger
def combo(x,y=10):
         time.sleep(2)
         return (x+10)*3-1
 
print(combo(40,y=97))

 

圖形化理解裝飾器的做用:::::::
 
一副畫不能隨便塗改,因此能夠在裱畫的同時,對畫外面的部分進行一些改動,達到既不改動畫的同時,又能達到改動的效果,而畫(業務代碼)只有一副,可是各類各樣的畫框(裝飾器函數)卻能夠有多種樣式
 
 
查詢一個函數的文檔:
爲何要寫文檔幫助,能夠幫你查找函數的附加信息,能夠方便你識別其功能
函數的幫助文檔只能在 第一行顯示
幫助文檔的首字母儘可能大寫
第一行寫概述 空一行,第三行再寫詳細描述
使用三引號,能夠換行
示例:
def add(x,y):
     '''this is function
 
     thx'''
     ret=x+y
     return ret
print(add.__doc__)
利用代參裝飾器,進行業務代碼外的函數文檔複製,使其內外一致
 
def copy_(src):
     def wapper(dct):
          src.__name__ =dct.__name__
          src.__doc__ =dct.__name__
          return dct
     return wapper
 
import datetime
import time
def logger(fn):
         @copy_(fn)   #原公式爲 @copy_.waper=>logger.warp=copy_.wapper(logger.warp)
         def warp(*args,**kwargs):
             '''
             this is function
 
             '''
             print('args={} kwargs={}.'.format(args,kwargs))
             start=datetime.datetime.now()
             ret = fn(*args,**kwargs)
   times=datetime.datetime.now() - start
             print('func {} need {}s.'.format(warp.__name__,times))
             return ret
  return warp
 
@logger
def combo(x,y=10):
   time.sleep(2)
   return (x+10)*3-1
 
print(combo(40,y=97))
 
def add(x,y):
     '''this is function
     x = int
     y = int
 
     thx'''
     ret=x + y
     return ret
print(add.__doc__)
瘋狂寫代碼之 代參函數裝飾器示例:
def coop(old):
     def cood(new):
          new.__name__=old.__name__
          new.__doc__=old.__doc__
      return new
return cood
 
import datetime
import time
 
def word(t):
     def dayss(fn):
          def wordadd(*args):
               '''this is wodradd wordadd '''
                 start=datetime.datetime.now()
                 print('im a super student')
                 tec=fn(*args)
                 end=(datetime.datetime.now() - start).total_seconds()
                 if end > t:
                     print('you program is so slow , you can write it again ')
                 else:
                     print('you need {}s to make this complete'.format(end))
                 return tec
           return wordadd
     return dayss
 
@word(t=50)
def add(x,y):
     '''this is add help words'''
     time.sleep(2)
     return x + y
 
print('''Function:{};
Helpword={};
The result of his executionis {}'''.format({add.__name__},{add.__doc__},{add(4,5)}))
代參裝飾器:
它是一個函數
函數爲他的形參
返回值是一個不帶參的裝飾器函數
使用@funcition(參數列表)方式調用
能夠看做在裝飾器外又加了一層函數
 
文檔字符串:
python 是文檔字符串DOCumentation Strings
在函數語句塊的第一行,通常是多行的文本,使用三引號
習慣:首字母大寫,第一行概述,空一行,第三行寫詳細描述
能夠使用特殊屬性 __doc__來訪問這個函數的文本文檔
查看方式:     help(函數對象)
 
裝飾器的反作用:
使用裝飾器後的函數所顯示出的文本文檔不在是被包裝函數的文本文檔信息,而是顯示包裝函數的文檔信息,因此在封裝函數的同時也要考慮函數對象的文檔信息是不是本身想要看到的
解決辦法1:
能夠再寫一個拷貝函數;
     new.__name__=old.__name__
     new.__doc__=old.__doc__
將此函數做爲裝飾器對業務代碼再次進行包裝,這樣所顯示的文本文檔就是最初的文本文檔了
凡是須要屬性複製的均可以調用這個裝飾器進行包裝,因此這個函數很通用
 
founctools模塊(須要導入)
functools.update__wrapper(wrapper,wrapped,assigned=WRAPPER__ASSIGNMENTS,updated=WRAPPER_UPDATES)
其功能和拷貝相似
wrapper包裝函數      wrapped被包裝函數
元組WRAPPER_ASSIGNMENTS中是要被覆蓋的屬性
'__module__,__name__,__doc__,__qualname__,__annotations__)' 
模塊,名字,文檔,限定名,參數註解
元組WRAPPER_UPDATES中是要被更新的屬性,__dict__ 屬性字典
增長一個_wrapped__屬性保留着wrapped函數
 
functools的用法:
import datetime,time,functools:
def logger(durtion,func=lambda name,duration:print('{} took {}s'.format(name,duration))):
     def __logger(fn):
          @functools(fn)
          def wrapped(*args):
      start = datetime.datetime.now()
      ret =  fn(*args)
      delta = (datetime.datetime.now()-start).total.seconds()
      if delta > duration:
             func(__name__,duration)
               return ret
         return  wrapped
     return __logger
 
@logger(5)               # add = logger(5(add)
def add(x,y):
     time.sleep(2)
     return x+y
 
print(add(5,6),add.__name__,add.__dict__,add.wrapped__,sep='\n')

溫故而知新,知識仍是要鞏固的呀python

相關文章
相關標籤/搜索