標籤:pre 列印 統計 其他 ora one 分享 invalid int
裝飾器decorator
(“器”代表的是函數)
定義:本質是函數
作用:用來裝飾其他函數 in other words,為其他函數添加附加功能
(eg. 假如程式已上線,如果想新增功能,但是又不能改原始碼)
原則:
1.不能修改被裝飾的函數的原始碼
2.不能修改被裝飾的函數的調用方試
組成:高階函數+嵌套函數 --> 裝飾器
Q: 高階\嵌套函數是個什麼鬼???
高階函數:
1.把一個函數當做實參傳給另一個函數(在不修改被裝飾函數原始碼的情況下為其添加功能)
import timedef bar(): time.sleep(3) print("in the bar")def test1(func): start_time = time.time() func() # run bar() stop_time = time.time() print("the func run time is %s"%(stop_time -start_time)) # 統計的是bar的已耗用時間test1(bar) # func = bar 所以可以進行func() 傳的記憶體位址test1(bar()) # 把bar()的傳回值傳進去了 傳的傳回值# BUT !調用方式變了,不是裝飾器
View Code
2.傳回值中包含函數名(不修改函數的調用方式)
import timedef bar(): time.sleep(3) print("in the bar")def test2(func): print(func) # 列印func的記憶體位址,也就是bar的記憶體位址 return func # return bar的記憶體位址bar = test2(bar)bar() # run bar
View Code
嵌套函數:
在一個函數的函數體內用def去申請另一個函數
#嵌套函數def foo(): print("in the foo") def bar(): # 相當於局部變數,所以不能在外面直接調用bar(),所以要寫在裡面 print("in the bar") bar()foo()# 這個不是函數的嵌套,這叫函數的調用def test1(): test2()test1()
View Code
EXAMPLE 1
最佳化(@timmer)
def timer(func): #timer(test1) 把test1的記憶體位址傳給func,func = test1 def deco(): start_time = time.time() func() # run test1 stop_time = time.time() print("the func run time is %s"%(start_time-stop_time)) return deco # 返回這個函數的記憶體位址@timer # 這就相當於 test1 = timer(test1)def test1(): time.sleep(3) print("in the test1")@timerdef test2(): time.sleep(3) print("in the test2")test1() test2() # 其實調用的是deco這個函數,因為timer(test1)的傳回值是deco的記憶體位址
View Code
最佳化(調用時傳入多個參數)
def timer(func): #timer(test1) 把test1的記憶體位址傳給func,func = test1 def deco(*args,**kwargs): start_time = time.time() func(*args,**kwargs) # run test1 stop_time = time.time() print("the func run time is %s"%(start_time-stop_time)) return deco # 返回這個函數的記憶體位址@timer # 這就相當於 test1 = timer(test1) = decodef test1(): time.sleep(1) print("in the test1")@timer # test2 = timer(test2) = deco# test2() = deco() 所以在deco裡加argsdef test2(name,age): print("test2:",name,age,)test1()test2("alex",22)
View Code
EXAMPLE 2 !!
import timeuser,passwd = "alex","abc123"def auth(auth_type): print("auth func:",auth_type) def outer_wrapper(func): def wrapper(*args,**kwargs): print("wrapper func args:",*args,**kwargs) if auth_type =="local": username = input("username:").strip() password = input("password:").strip() if user == username and passwd == password: print("\033[32;1mUser has passed authenfication\033[0m") res = func(*args,**kwargs) # return from home print("------after authenficaiton") return res else: exit("\033[31;1mInvalid username or password\033[0m") elif auth_type == "ladp": print("毛線ldap,不會------") return wrapper return outer_wrapperdef index(): # 首頁 print("welcome to index page")@auth(auth_type = "local") # 本地認證 & home = wrapper()def home(): # 使用者登入後的首頁 print("welcome to home page") return "from home"@auth(auth_type = "ldap") # 遠程認證def bbs(): # 論壇 print("welcome to bbs page")index()print(home()) # return None 如果沒有return func()的話bbs()
View Code
ps:
函數及變數
# 沒問題def bar(): print("in the bar")def foo(): print("in the foo") bar()foo()# bar定義到下面也是可以啟動並執行def foo(): print("in the foo") bar()def bar(): print("in the bar")foo()# 會報錯,因為函數和變數一樣,是先定義,在調用。所以會報錯def foo(): print("in the foo") bar()foo()def bar(): print("in the bar")
View Code
產生器generator
原理:只有在調用時才會產生相應的資料(假如一個大資料,只循壞了前5次,那麼後面的資料是沒有準備好的)
作用:省記憶體
特點:產生器只記住當前位置(不管前後),不能後退回返,也不能跳著走
只有一個next方法: __next__()
ps:
列表產生式
>>>print([i*2 for i in range(10)])[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]>>>>>>[func(i) for i in range(10)] # 傳函數也可以
Long Way To Go 之 Python 4