簡體   English   中英

嘗試打印 *args 和 **kwargs 時出現奇怪的錯誤

[英]Getting weird errors when trying to print *args and **kwargs

所以我正在制作一個計時器包裝器 function,但是在嘗試打印 arguments 時,我不斷收到錯誤消息。

我的計時器 function 看起來像這樣:

def time_me(fn):
    from time import time as t
    def wrapper(*args, **kwargs):
        start_time = t()
        fn(*args, **kwargs)
        end_time = t()
        print("executing {} with arguments {}, took: {}".format(fn.__name__, *args, end_time - start_time))
        return fn(*args, **kwargs)
    return wrapper

理想情況下,它也會打印 kwargs,但顯然這是另一個問題,盡管如果有人幫助我,我將不勝感激。 因此,當沒有一個論點時,我所擁有的效果很好:

@time_me
def dummy_fn(N):
    from time import sleep as ts
    ts(0.2)
    return 

dummy_fn(1000)

給我:用 arguments 1000 執行 dummy_fn,占用:0.2128157615661621

但是,如果我重新定義 dummy_fn 以獲取更多 arguments 並通過它們,它仍然只打印第一個。 當我嘗試將我的 *args 轉換為字符串時,我收到錯誤消息說“str() 參數 2 必須是 str,而不是 int”。 我似乎也無法使用例如 list() function 訪問我的 *args。

有誰知道如何解決這個問題?

在 function 簽名中使用*args將所有位置 arguments 打包到單個元組args中。 然后,如果您在 function 主體內的另一個.format調用中說*args ,它會將其傳播回多個 arguments11,因為您不想要它,因為它會弄亂您的論點,並做一些事情,例如它。 str(*args)失敗,因為現在您將多個 arguments 傳遞給str function。 只需按原樣傳遞args ,它將被格式化為合適的字符串。

另請注意,您的包裝器兩次調用包裝的 function ,這是您可能不想要的(從那時起,實際上運行時間是您測量的時間的兩倍,副作用正在重復,等等)。 它應該調用一次(在計時器內),記住結果,然后返回結果。

這是一個固定版本:

def time_me(fn):
    from time import time as t
    def wrapper(*args, **kwargs):
        start_time = t()
        result = fn(*args, **kwargs)
        end_time = t()
        print(f"executed {fn.__name__} with arguments {args} and {kwargs}, took: {end_time - start_time}")
        return result
    return wrapper

如果您不喜歡result =...模式,您可以使用上下文管理器:

from contextlib import contextmanager
from functools import wraps
from time import time

def time_me(fn):
    @contextmanager
    def timed_context(desc):
        start_time = time()
        try:
            yield
        finally:
            end_time = time()
            print(f"executed {desc}, took: {end_time - start_time}")

    @wraps(fn)
    def wrapper(*args, **kwargs):
        with timed_context(f"{fn.__name__} with arguments {args} and {kwargs}"):
            return fn(*args, **kwargs)

    return wrapper

(為什么是@wraps(fn) ?你已經知道fn.__name__ ,但是你知道如果你在由 time_me 裝飾的 function 上使用.__name__ time_me它現在會說wrapper而不是原來的 function?你可以functools.wraps裝飾器,它適用於包裝器 function 並使其“看起來像”包裝的 function。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM