我有一個簡單的裝飾器,它應該列印所有函式引數。并且假設我們有一些小函式和這個函式的一個包裝器,并且想要記錄這個包裝器函式。
問題是由于某種原因引數不起作用,我得到一個錯誤
您將如何重寫函式 log_step 以便它允許我們關閉和打開用于列印函式引數的引數?
from functools import wraps
import inspect
def log_step(func, print_params = False):
@wraps(func)
def wrapper(*args, **kwargs):
tic = dt.datetime.now()
result = func(*args, **kwargs)
time_taken = str(dt.datetime.now() - tic)
print(f"function {func.__name__} took {time_taken}s")
if print_params is not False:
func_args = inspect.signature(func).bind(*args, **kwargs).arguments
func_args_str = ", ".join(map("{0[0]} = {0[1]!r}".format, func_args.items()))
print(f"{func.__name__} arguments: \n==================\n{func_args_str} \n==================\n")
return result
return wrapper
def _simple_inside_function(name:str, age:int) -> str:
"""
Simple Inside function that prints your name and age
"""
age = age 10
print(f"Hello {name}, who is {age} years old.")
return age
@log_step(print_params = True)
def wrapper_print_name(config: dict) -> str:
"""
wrapper function
I am spider man
"""
A = _simple_inside_function(**config)
return A
uj5u.com熱心網友回復:
不確定是否有更優雅的使用方式functools,但據我所知,帶引數的裝飾器需要三個函式:(a) 裝飾器函式,接受一個引數并創建 (b) 另一個函式,將原始函式作為引數, 回傳 (c) 函式的修飾版本,采用原始函式的引數,使用預處理/后處理呼叫函式并回傳其結果,即:
def log_step(print_params = False):
def inner(func):
@wraps(func)
def wrapper(*args, **kwargs):
...
return result
return wrapper
return inner
只有當裝飾器不帶引數時,才不需要最外層的函式。這看起來怪異和不一致,但更有意義,如果你認為@deco func是類似于func = deco(func)和@deco(args) func被類似func = deco(args)(func)。因此,如果您想使用不帶引數的裝飾器,您可以這樣做(注意括號):
@log_step()
def wrapper_print_name(config: dict) -> str:
如果你想不帶(),即
@log_step
def wrapper_print_name(config: dict) -> str:
可能沒有辦法為print_params或 函式本身濫用相同的引數。這很hacky,但functools似乎對 做同樣的事情lru_cache,它可以用作@lru_cache(size), @lru_cache(),或者只是@lru_cache:
def lru_cache(maxsize=128, typed=False):
...
if isinstance(maxsize, int):
...
elif callable(maxsize) and isinstance(typed, bool):
....
uj5u.com熱心網友回復:
log_step應該是一個函式,它接受一個布爾引數并回傳一個接受裝飾函式并回傳一個包裝器的函式。換句話說,log_step是一個產生裝飾器的函式,_它將用于包裝被裝飾的函式。
def log_step(print_params=False):
def _(func):
@wraps(func)
def wrapper(*args, **kwargs):
tic = dt.datetime.now()
result = func(*args, **kwargs)
time_taken = str(dt.datetime.now() - tic)
print(f"function {func.__name__} took {time_taken}s")
if print_params:
func_args = inspect.signature(func).bind(*args, **kwargs).arguments
func_args_str = ", ".join(map("{0[0]} = {0[1]!r}".format, func_args.items()))
print(f"{func.__name__} arguments: \n==================\n{func_args_str} \n==================\n")
return result
return wrapper
return _
您當前正在定義一個函式,該函式需要一個函式和一個布林值作為引數,但在您使用它時只傳遞布林值。
您甚至可以使用print_paramsinside的值log_step來定義兩個不同函式之一,以避免print_params每次呼叫裝飾函式時都必須檢查(不變)值。
def log_step(print_params=False):
if print_params:
def _(func):
@wraps(func)
def wrapper(*args, **kwargs):
tic = dt.datetime.now()
result = func(*args, **kwargs)
time_taken = str(dt.datetime.now() - tic)
print(f"function {func.__name__} took {time_taken}s")
func_args = inspect.signature(func).bind(*args, **kwargs).arguments
func_args_str = ", ".join(map("{0[0]} = {0[1]!r}".format, func_args.items()))
print(f"{func.__name__} arguments: \n==================\n{func_args_str} \n==================\n")
return result
return wrapper
else:
def _(func):
@wraps(func)
def wrapper(*args, **kwargs):
tic = dt.datetime.now()
result = func(*args, **kwargs)
time_taken = str(dt.datetime.now() - tic)
print(f"function {func.__name__} took {time_taken}s")
return result
return wrapper
return _
您可能希望將其重構為類似
def log_step(print_params=False):
def foo(func, **args, **kwargs):
tic = dt.datetime.now()
result = func(*args, **kwargs)
time_taken = str(dt.datetime.now() - tic)
print(f"function {func.__name__} took {time_taken}s")
return result
def param_printer(func, *args, **kwargs):
func_args = inspect.signature(func).bind(*args, **kwargs).arguments
func_args_str = ", ".join(map("{0[0]} = {0[1]!r}".format, func_args.items()))
print(f"{func.__name__} arguments: \n==================\n{func_args_str} \n==================\n")
if print_params:
def _(func):
@wraps(func)
def wrapper(*args, **kwargs):
result = foo(func, *args, **kwargs)
param_printer(func, *args, **kwargs)
return result
return wrapper
else:
_ = @wraps(func)(foo)
return _
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/343730.html
上一篇:PythonPandas基于另一個對應資料框合并兩個資料框
下一篇:Selenium如何獲取文本元素
