python編寫裝飾器_我也來寫一下python裝飾器

有借用,但原文出處已經找不到了,根據筆記分享一下解釋器的基礎。

下面的代碼表示,等待兩秒鐘,輸出‘test is running'。

現在要求增加統計程序運行時間的功能。

等待兩秒鐘,輸出‘test is running',現要求增加統計程序運行時間的功能。

import time

def test():

time.sleep(2)

print('test is running!')

test()

學習先問為什么,有什么用,學基礎的時候有時不理解為什么簡單的事情要搞那么復雜,而對應的實際應用時,往往“這個復雜方法有很多優點和簡化了很多事情”。學基礎時用簡單的例子,只是為了講明知識點,而不要去關注例子實現的什么功能,這個功能當然是個‘屁’了。

那么,裝飾器的實際應用場景:程序已上線或已使用,但需要增加新功能,修改原函數不合理也不科學(這里真的包含了很多背景聲音),就要求:

(1)不能修改原功能函數的代碼。例子中的功能是非常簡單的,要實現當然是直接修改,但現實中一個功能的實現是非常復雜的代碼,直接修改是不合理不科學的。

(2)不能修改原函數的調用方式。在符合第一條的情況下,調用時仍然是用test(),即老方法能實現新功能。現實中后面程序在反復用test(),就是要完全不動老代碼的基礎上,增加一個’裝飾器‘更新整個程序。

(3)上述說的老方法是表面上的,這就是裝飾器介入的作用。

好,以下開始改造,用試錯的方法解釋裝飾器的實現過程和原理。

滿足條件(1)可以增加代碼如下:

def deco(func):

start=time.time()

func()

stop=time.time()

print(stop-start)

deco(test)

#把老代碼里的test函數作為參數傳遞給新函數

#(因為是增加新功能,老功能還是要的,所以新代碼里肯定要引用老代碼的功能,就采取了這種方法)

看上去新功能就實現了,但可以看到調用方式變為了deco(test),即違背了條件(2),以前程序里可能反復調用了test(),都要改成deco(test),不科學。

同時滿足條件(2),再改:

思路:產生一個新函數,重新賦值給test,test=某函數,那么后面反復調用的test()就被實質上改過來了,實現功能。

#試一下:

test=deco(test) #計算右邊的,是一個兩行字符串,賦值給test根本不是一個函數。

test() #因此跳錯誤碼

再試一下:

增加:return func

然后:

test=deco(test)

test()

代碼正常運行,但因為return func的縮進和其他代碼是同級的,所以deco(test)這步已經把新功能給實現了,又返回了一次test(),結果重復。

把下面完整的代碼去試一下,出現了兩次test is running ,不合格。

import time

def test():

time.sleep(2)

print('test is running!')

def deco(func):

start=time.time()

func()

stop=time.time()

print(stop-start)

return func

test=deco(test)

test()

思路沒有錯,上述這里return一個函數的思考過程也是對的,只是返回的方式不對,應當使用’嵌套函數‘。

def timer(func):

def deco():

start=time.time()

func()

stop=time.time()

print(stop-start)

return deco

#把deco()嵌套在timer(func)里,返回一個deco()函數的函數名deco;

#調用timer(func)時,deco()里面的過程代碼類似于沒有執行的,

#被打包成了一個函數,執行的只是return了這個函數的函數名。

test=timer(test)

#右邊代碼返回的是一個deco()的函數名deco,deco()打包了作為被參數傳入的原test()里的功能,

#同時增加了新功能。

test()

#符合(2)要求,沒有改變調用方法,但實質上這句調用的已經是deco()了。

#頂格代碼是不能調用經過了二次縮進的嵌套函數的,

#但這里用了deco()用了return,成了閉包函數,就可以被調用了。

至此,本質上是修改了調用函數,但在表面上并未修改調用方式,而且實現了附加功能,需求實現。

真正的裝飾器:語法糖

在原test()的上一行加上@timer,刪除test=timer(test).

而且要把新增的函數寫在原函數的上面

最后代碼

import time

def timer(func):

print(func.__name__) #看看打印出來的是什么

def deco():

start=time.time()

func()

stop=time.time()

print(stop-start)

return deco

@timer

def test():

time.sleep(2)

print('test is running')

#test=timer(test)這句不用了,注釋掉

test()

過程比較啰嗦,但每一步都看下來后,裝飾 器的原理就知道了,涉及到有參數的時候,再另外理解了。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455289.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455289.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455289.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

VirtualBox安裝Centos6.8出現——E_INVALIDARG (0x80070057)

VirtualBox使用已有的虛擬硬盤出錯: 問題描述:UUID已經存在 Cannot register the hard disk E:\system_iso\centos6.8.vdi {05f096aa-67fc-4191-983d-1ed00fc6cce9} because a hard disk E:\system_iso\centos68_02\centos6.8.vdi with UUID {05f096aa-6…

DFT 與 ATPG綜 述

DFT 可測試性設計 工程會接觸 DFT。需要了解 DFT 知識,但不需要深入。 三種基本的測試(概念來自參考文檔): 邊界掃描測試:Boundary Scan Test: 測試目標是 IO-PAD,利用 JTAG 接口互連以方便 測試。&#x…

非線性動力學_非線性動力學特輯 低維到高維的聯通者

序言: 本文將以維度為主線, 帶量大家進入非線性動力學的世界。 文章數學部分不需要全部理解, 理解思維方法為主非線性動力學,是物理學的思維進入傳統方法所不能解決的問題的一座豐碑。它可以幫助我們理解不同復雜度和時間空間尺度…

Go語言channel與select原理

本文會嘗試解釋 go runtime 中 channel 和 select 的具體實現,部分內容來自 gophercon2017。Go版本為1.8.3channel 第一部分講述一下 channel 的用法。channel 可以看做一個隊列,用于多個goroutine之間的通信,例如下面的例子,一個…

Xadmin添加用戶小組件出錯

環境: Python 3.5.6 Django 2.1 Xadmin 原因: render函數在django2.1上有變化 解決方案: 1.在Python終端輸入命令help(xadmin) 查看xadmin安裝位置 得到如下輸出 FILE/root/anaconda3/envs/learndjango/lib/python3.5/site-packages/xad…

成本預算的四個步驟_全網推廣步驟有哪些?

全網推廣的步驟是什么?一般來說,搜索引擎優化是大多數中小企業常用的推廣方法。主要是通過對一些搜索引擎的排名來提高網站的曝光率,從而更好的提高自己網站的流量,從而更好的實現互聯網層面的銷售。接下來,讓我們學習…

undefined reference to `std::cout'等錯誤

(1)gcc和g都是GNU(組織)的一個編譯器。 (2)后綴名為.c的程序和.cpp的程序g都會當成是c的源程序來處理。而gcc不然,gcc會把.c的程序處理成c程序。 (3)對于.cpp的程序,編譯可以用gcc/g…

FFPLAY的原理(二)

關于包Packets的注釋從技術上講一個包可以包含部分或者其它的數據,但是ffmpeg的解釋器保證了我們得到的包Packets包含的要么是完整的要么是多種完整的幀。現在我們需要做的是讓SaveFrame函數能把RGB信息定稿到一個PPM格式的文件中。我們將生成一個簡單的PPM格式文件…

python生成requirements.txt的兩種方法

python項目如何在另一個環境上重新構建項目所需要的運行環境依賴包? 使用的時候邊記載是個很麻煩的事情,總會出現遺漏的包的問題,這個時候手動安裝也很麻煩,不能確定代碼報錯的需要安裝的包是什么版本。這些問題,requi…

node.js 安裝使用http-server

node.js npm全局安裝了http-server后我該怎么使用它?我在它的安裝目錄下創建了inde.html,瀏覽器localhost:8080可以訪問,那我的項目需要放在它的安裝目錄下?還是需要在我的項目下配置什么或者使用什么指令啟動它?我在我…

D - 卿學姐與魔法

卿學姐與魔法 Time Limit: 1200/800MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit Status“你的膜法也救不了你 在去拯救公主的道路上,卿學姐披荊斬棘,刀刃早已銹跡斑斑。 一日卿學姐正在為武器的問題發愁,碰到了正…

python對excel表統計視頻教程_Python實現對excel文件列表值進行統計的方法

本文實例講述了Python實現對excel文件列表值進行統計的方法。分享給大家供大家參考。具體如下:#!/usr/bin/env python#codinggbk#此PY用來統計一個execl文件中的特定一列的值的分類import win32com.clientfilenameraw_input("請輸入要統計文件的詳細地址&#…

mooc后臺管理系統設計

摘 要 本設計采用Python中的Django框架實現Mooc后臺管理界面設計,django是一個完整的開源web開源框架,使用起來能夠快速的搭建你想要的網站,由于django自帶后臺管理系統,本設計中后臺管理模板采用功能更加強大的Xadmin實現。數據庫部分采用mysql5.7,由于django中有自帶封裝的數…

DirectShow系統初級指南

流媒體的處理,以其復雜性和技術性,一向廣受工業界的關注。特別伴隨著因特網的普及,流媒體在網絡上的廣泛應用,怎樣使流媒體的處理變得簡單而富有成效逐漸成為了焦點問題。選擇一種合適的應用方案,事半功倍。此時&#…

正則正整數含0

^0?$|^([1-9][0-9]*)?$

MySQL 數據庫導出導入操作

有時需要將 MySQL 數據庫中的數據導入到其它的數據庫中,這里以從 Ubuntu 系統的 MySQL 數據庫導出 zabbix 這個數據庫到 Windows 系統中的MySQL 為例。 導出數據庫 導出數據其實非常方便,比如將 MySQL 中的 zabbix 這個數據庫導出到當前文件夾&#xff…

您的apple id 暫時不符合使用此應用程序_Mac相機不工作時該怎么辦

蘋果公司的許多臺式機和筆記本電腦都包含一個內置網絡攝像頭,該公司愉快地將其稱為FaceTime相機。但是,如果您的Mac網絡攝像頭無法正常工作,并且在嘗試訪問它時顯示為斷開連接或不可用,則您可能不會感到高興。您可以嘗試以下操作來…

基于DirectShow的流媒體解碼和回放

一、 前言  流媒體的定義很廣泛,大多數時候指的是把連續的影像和聲音信息經過壓縮處理后放上網站服務器,讓用戶一邊下載一邊觀看、收聽,而不需要等整個壓縮文件下載到自己機器就可以觀看的視頻/音頻傳輸、壓縮技術。流媒體也指代由這種技術…

《知易行難》擴展練習

在學習了《知易行難》后,這個是一個選做的擴展練習,但是里面的問題真的的很好,所以我也將在這里真實的分享,但是有些敏感的人名我就隱去了。 1. 這一年你做了些什么事情? 1)團隊的整合,將團隊…

python 裁判文書網_python - 用selenium模擬登陸裁判文書網,系統報錯找不到元素。...

問 題from selenium import webdriverfrom selenium.webdriver.common.desired_capabilities import DesiredCapabilitiesdcap dict(DesiredCapabilities.PHANTOMJS)dcap["phantomjs.page.settings.userAgent"]("Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWeb…