function與inner function
-
function:在python中,function就像其他物件一樣,可以當做引數或回傳值,當函式作為回傳值時,不要帶括號,表示其會在將來被呼叫,
-
inner function:一個函式A(inner function)定義在另一個函式B中,函式A不能直接被外界呼叫,因此此時內部函式還未定義,但可以通過B將A的參考回傳,用于在將來呼叫,
# 函式用做引數
def hello():
print("hello")
def welcome():
print("Welcome")
def say_something(func):
func()
# 函式A在函式B中定義,并且用做回傳值
def cal():
def add(a,b):
print(a+b)
return add

decorator
裝飾器就是結合了內部函式以及函式在python中是一級公民(可以用做引數、回傳值)的性質,
decorator:封裝了一個函式,并且改變了其行為
def hello():
print("hello")
def my_decorator(func):
def wrapper():
print("before func work")
func()
print("after func work")
return wrapper
hello_d = my_decorator(hello)
hello_d()
"""
before func work
hello
after func work
"""
hello_d便是經過my_decorator裝飾的函式,為使程序更加簡化,python提供了語法糖,
syntactic sugar
@my_decorator
def hello():
print("hello")
def my_decorator(func):
def wrapper():
print("before func work")
func()
print("after func work")
return wrapper
hello()#與hello = my_decorator(hello)作用相同
"""
before func work
hello
after func work
"""
wrapper的命名可自定義,
使用@functools.wrap(func)
因為hello被my_decoratorx裝飾過,此時在python shell查看hello的__name__,發現

這對我們來說,不是有用的資訊,為了“正確”顯示,使用@functools.wrap(func)
import functools
@my_decorator
def hello():
print("hello")
def my_decorator(func):
@functools.wrap(func)
def wrapper():
print("before func work")
func()
print("after func work")
return wrapper

帶引數的decorator以及幾個例子
# do twice
def do_twice(func):
@functools.wraps(func)
def wrapper(*args,**kwargs):
func(*args,**kwargs)
func(*args,**kwargs)
return wrapper
# timer
def timer(func):
@functools.wraps(func)
def wrapper_timer(*args, **kwargs):
start_time = time.perf_counter()
value = https://www.cnblogs.com/pitaya01/p/func(*args, **kwargs)
end_time = time.perf_counter()
run_time = end_time - start_time
print(f"Finished {func.__name__} in {run_time:.4f} seconds")
return value
return wrapper_timer
@timer
def waste_time(num):
for _ in range(num):
sum([i **2 for i in range(10000)])
waste_time(1000)
# flask check user login
def login_required(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
if g.user is None:
return redirect(url_for('login',next=request.url))
return func(*args, **kwargs)
return wrapper
@app.route('/secret')
@login_required
def secret():
...
總結
decorator用于“包裹”一個函式,改變其行為,
在wrapper中并不一定要執行該函式,也可以保留函式的參考,用于插件的注冊,
參考
realpython
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/486599.html
標籤:Python
