20181130(裝飾器補充,疊加多個裝飾器,有參裝飾器,三元表達式,生成式,匿名函數,內置函數)

来源:https://www.cnblogs.com/realadmin/archive/2018/11/30/10046685.html
-Advertisement-
Play Games

1、函數屬性的傳遞 1、疊加多個裝飾器 載入順序(outter函數的調用順序):自下而上 執行順序(wrapper函數的執行順序):自上而下 2、有參裝飾器:三層的閉包函數 對於裝飾器,三層就夠了(第一層傳參數,第二層傳函數,第三層執行添加的功能和源代碼) 只能將if else這種簡單的取代,有el ...


 

一、裝飾器的補充

1、函數屬性的傳遞

Python裝飾器(decorator)在實現的時候,被裝飾後的函數其實已經是另外一個函數了(函數名等函數屬性會發生改變),為了不影響,Python的functools包中提供了一個叫wraps的decorator來消除這樣的副作用。寫一個decorator的時候,最好在實現之前加上functools的wrap,它能保留原有函數的名稱和docstring。
簡言之:導入wraps,即可將原函數的屬性(解釋文本等)傳遞給裝飾器中對應的函數。
from functools import wraps  #從 functools導入wraps

def outter(func):
   @wraps(func)  #相當於一個裝飾器,將func的屬性傳遞給wraps
   def wrapper(*args,**kwargs):
       res=func(*args,**kwargs)
       return res
   return wrapper

@outter #index=outter(index) #index=wrapper
def index():
   """
  這是index函數....
  """
   print('from index')


index()
print(index.__doc__)  #輸出index的說明文檔
print(index.__name__)  #輸出index的名字,index是函數的記憶體地址
輸出結果為:
from index

   這是index函數....
   
index

 

1、疊加多個裝飾器

載入順序(outter函數的調用順序):自下而上

執行順序(wrapper函數的執行順序):自上而下

# 疊加多個裝飾器
# 1. 載入順序(outter函數的調用順序):自下而上
# 2. 執行順序(wrapper函數的執行順序):自上而下


def outter1(func1): #func1=wrapper2的記憶體地址
   print('載入了outter1')
   def wrapper1(*args,**kwargs):
       print('執行了wrapper1')
       res1=func1(*args,**kwargs)
       return res1
   return wrapper1

def outter2(func2): #func2=wrapper3的記憶體地址
   print('載入了outter2')
   def wrapper2(*args,**kwargs):
       print('執行了wrapper2')
       res2=func2(*args,**kwargs)
       return res2
   return wrapper2

def outter3(func3): # func3=最原始的那個index的記憶體地址
   print('載入了outter3')
   def wrapper3(*args,**kwargs):
       print('執行了wrapper3')
       res3=func3(*args,**kwargs)
       return res3
   return wrapper3



@outter1 # outter1(wrapper2的記憶體地址)======>index=wrapper1的記憶體地址
@outter2 # outter2(wrapper3的記憶體地址)======>wrapper2的記憶體地址
@outter3 # outter3(最原始的那個index的記憶體地址)===>wrapper3的記憶體地址
def index():
   print('from index')

print('======================================================')
index()
輸出結果為:
載入了outter3
載入了outter2
載入了outter1
======================================================
執行了wrapper1
執行了wrapper2
執行了wrapper3
from index

 

 

import time

def timmer(func):
   def aaa(*args,**kwargs):
       start=time.time()
       res=func(*args,**kwargs)
       stop=time.time()
       print('run time is %s' %(stop -start))
       return res
   return aaa

def auth(func):
   def bbb(*args,**kwargs):
       name=input('name>>>: ').strip()
       pwd=input('pwd>>>: ').strip()
       if name == 'egon' and pwd == '123':
           print('login successfull')
           res=func(*args,**kwargs)
           return res
       else:
           print('user or pwd error')
   return bbb

@auth
@timmer  #註意此處裝飾器的先後順序,調整裝飾器的先後順序,會得到不同的結果。
def index():
   time.sleep(1)
   print('from index')

index()

 

2、有參裝飾器:三層的閉包函數

對於裝飾器,三層就夠了(第一層傳參數,第二層傳函數,第三層執行添加的功能和源代碼)

import time
from functools import wraps
current_user={'user':None}

def auth(engine='file'):
   def outter(func):
       @wraps(func)
       def wrapper(*args,**kwargs):
           if current_user['user'] is not None:
               res=func(*args,**kwargs)
               return res

           user=input('username>>>: ').strip()
           pwd=input('password>>>: ').strip()

           if engine == 'file':
               # 基於文件的認證
               if user == 'egon' and pwd == '123':
                   print('login successfull')
                   current_user['user']=user
                   res=func(*args,**kwargs)
                   return res
               else:
                   print('user or password error')
           elif engine == 'mysql':
               # 基於mysql的認證
               print('基於mysql的認證')
           elif engine == 'ldap':
               # 基於ldap的認證
               print('基於ldap的認證')
           else:
               print('不知道engine')
       return wrapper
   return outter

@auth('ldap') #@outter #index=outter(index) # index=wrapper #註意此處傳參的方法
def index():
   time.sleep(1)
   print('from index')

@auth('mysql') #@outter # home=outter(home) #home=wrapper #註意此處傳參的方法
def home(name):
   print('welcome %s' %name)

index()
home('egon')

輸出結果:
username>>>: egon
password>>>: 123
基於ldap的認證
username>>>: egon
password>>>: 123
基於mysql的認證

 

二、三元表達式

只能將if else這種簡單的取代,有elif的不行。

res='ok' if False else 'no'  #條件成立輸出左側的值,否則輸出右側的值,可以簡化if。。。else語句。
print(res)
輸出結果為:
no
三、生成式

列表生成式

# l=[]
# for i in range(10):
#     if i>4:
#         l.append(i**2)
# print(l)  
上下代碼功能一致
l=[i**2 for i in range(10) if i >4]  #後面不能使用else,無論是if else還是for else,可以對迴圈的參數進行操作
print(l)
輸出結果為:
[25, 36, 49, 64, 81]


# 映射和判斷
names=['egon','go_on','kevin','wxx']
print([name.upper() for name in names]) #映射關係
print([name for name in names if name.endswith('on')])  #判斷關係
print([name.upper() for name in names if name.endswith('on')])  #映射疊加判斷關係
輸出的結果:
['EGON', 'GO_ON', 'KEVIN', 'WXX']
['egon', 'go_on']
['EGON', 'GO_ON']

 

字典生成式:key和value需要有對應關係才好處理。

res={i:i**2 for i in range(10) if i > 3} #註意字典的生成格式
print(res)

print({i for i in 'hello'})  #註意此處生成的是集合!
輸出結果為:
{4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
{'e', 'h', 'l', 'o'}

 

四、匿名函數:匿名函數就是只定義了一個函數的記憶體地址,主要用於臨時使用一次的場景。
a=(lambda x,y:x+y)(1,2)  #格式為“lambda 參數:表達式”後接括弧內輸入參數,匿名函數自帶return,可以得到返回值
print(a)
輸出結果為3

 

五、內置函數

1、max和min

print(max([10,11,-3,23]))  #max會從列表中先取出兩個值比較,再將較大的和下一個值比較
輸出結果為:
23
比較value的值,然後輸出對應的key:
salaries={
   'egon':3000,
   'alex':100000000,
   'wupeiqi':10000,
   'yuanhao':2000
}

def func(k):
   return salaries[k]

print(max(salaries,key=lambda k:salaries[k]))  #此處第一個salaries是一個序列,其中的元素會被遍歷,作為參數k進行函數的運算,不理解的話看下麵
print(min(salaries,key=func))  #其實沒有必要做成有名函數,匿名函數就可以了。
# for迴圈的結果         比較依據
# 'egon'               3000
# 'alex'               100000000
# 'wupeiqi'             10000
# 'yuanhao'             2000
輸出結果為:
alex
yuanhao

max的解釋:
max(iterable, *[, key, default])
max(arg1, arg2, *args[, key])
字典是可迭代的,結果為key值,
salaries={
   'egon':3000,
   'alex':100000000,
   'wupeiqi':10000,
   'yuanhao':2000
}

l=list(salaries)
print(l)
輸出結果為:
['egon', 'alex', 'wupeiqi', 'yuanhao']

res=max((1,2),[1,1],key = lambda x : x[1])
print(res)
輸出結果為:
(1, 2)

sorted函數:

def sorted(*args, **kwargs): # real signature unknown
  """
  Return a new list containing all items from the iterable in ascending order.
   
  A custom key function can be supplied to customize the sort order, and the
  reverse flag can be set to request the result in descending order.
  """
   
以升序返回包含iterable中所有項的新列表。
可以提供自定義鍵功能來自定義排序順序,以及可以設置反向標誌以按降序請求結果。

 

匿名函數與其他函數的結合應用:

salaries={
   'egon':3000,
   'alex':100000000,
   'wupeiqi':10000,
   'yuanhao':2000
}
print(sorted(salaries,key=lambda k:salaries[k],reverse=True)) #字典中的key變成序列作為參數傳入後面的匿名函數,由升序改為降序排列。
輸出結果為:
['alex', 'wupeiqi', 'egon', 'yuanhao']

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 準備: (1)Kali Linux系統(此實驗為VMware環境) (2)Go語言安裝包 具體過程: (1)到官網下載Go語言安裝包,如圖示操作(官網可能需要梯子,沒有的可以從國內相關網站下載) (2)下載好安裝包後,進行解壓操作,如圖所示 命令:tar zxvf gol.11.2.linux-am ...
  • 工具有: 樹莓派zero v1.3 CH340 USB轉串口工具 電腦端的串口調試助手 硬體接線如圖: 配置: 樹莓派的串口預設為串口終端調試使用,如要正常使用串口則需要修改樹莓派設置。關閉串口終端調試功能後則不能再通過串口登陸訪問樹莓派,需從新開啟後才能通過串口控制樹莓派。首先釋放串口,執行如下命 ...
  • 註意:以下代碼均針對python3.x ,python2.x 需要把括弧去掉 ,如:print ''This is the python 2. x format '' 1.print([object, ..., ]*, sep=' ', end='\n', file=sys.stdout,flush ...
  • 1.生鮮電商平臺的價值與定位。 生鮮電商平臺是一家致力於打造全國餐飲行業智能化、便利化、平臺化與透明化服務的創新型移動互聯網平臺,連接買家與賣家之間的一個平臺 看以下的圖標:(商業模式) 名稱解釋: 買家:所有的大中小型餐館,酒店等餐飲行業都屬於我們常說的買家。 生鮮電商APP: 買家通過在APP上 ...
  • APDL代碼實現link180單元的使用 由於不知道怎樣使用LINK180單元,故按照相關的教程和理解,整理了一下比較完整的APDL的代碼。其中包含的圖片的保存和背景顏色的改變。 標簽:'LINK180' ' APDL' [toc] APDL代碼 FINISH /CLEAR /PREP7 ET,1, ...
  • 目的:實現壓縮包的自動解壓及刪除。 思路:獲取壓縮包 > 解壓 > 刪除壓縮包 代碼實現:此處代碼實現前提為.py文件和壓縮包在同一文件夾 結果:.zip文件一旦出現,則立刻被解壓並刪除 ...
  • 1.什麼是字典 字典是以key:value的形式來保存數據,用{}表示. 存儲的是key:value 坑: 字典存儲數據的時候是用的hash值來存儲. 演算法不能變(python的) # 數據必須是不可變的(可哈希). 字典的key必須是可哈希的(不可變). dic = {"jay":"周傑倫", " ...
  • 程式爬取目標 獲取博客園精華區文章的 標題、標題鏈接、作者、作者博客主頁鏈接、摘要、發佈時間、評論數、閱讀數和推薦數, 並存儲到 MongoDB 中。 程式環境 已安裝scrapy 已安裝MongoDB 創建工程 在命令提示符中執行上述命令後,會建立一個名為 的文件夾。 創建爬蟲文件 執行上述命令後 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...