簡體   English   中英

在多次調用的函數Python 3中執行一次昂貴的操作

[英]Expensive operation done once in a function that is called many times, Python 3

我在json中有很長的組列表,我想要一個小實用程序:

def verify_group(group_id):
    group_ids = set()
    for grp in groups:
        group_ids.add(grp.get("pk"))
    return group_id in group_ids

一種明顯的方法是將集合加載到函數外部,或者以其他方式聲明全局變量-但讓我們假設我不需要全局變量。

在靜態類型語言中,我可以說該集合是靜態的,並且我相信這將實現我的目標。 在python中如何做類似的事情? 即:第一個調用初始化集合group_ids ,后續調用使用在第一個調用中初始化的集合。

順便說一句,當我使用profilestats包來分析這個小代碼片段時,我看到了這些令人恐懼的結果:

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      833    0.613    0.001    1.059    0.001 verify_users_groups.py:25(verify_group)
  2558976    0.253    0.000    0.253    0.000 {method 'get' of 'dict' objects}
  2558976    0.193    0.000    0.193    0.000 {method 'add' of 'set' objects}

我嘗試添加functools.lru_cache-但是這種類型的優化不能解決我目前的問題-如何 def塊中一次加載set group_ids

感謝您的時間。

沒有等效的static ,但是您可以通過不同的方式實現相同的效果:

一種方法是濫用臭名昭著的可變默認參數:

def verify_group(group_id, group_ids=set()):
    if not group_ids:
        group_ids.update(grp.get("pk") for grp in groups)
    return group_id in group_ids

但是,這允許調用者更改該值(這可能是您的功能或錯誤)。

我通常更喜歡使用閉包:

def make_group_verifier():
    group_ids = {grp.get("pk") for grp in groups}
    def verify_group(group_id):
        # nonlocal group_ids # if you need to change its value
        return group_id in group_ids
    return verify_group

verify_group = make_group_verifier()

Python是一種OOP語言。 您描述的是一個實例方法。 用集合初始化類,然后在實例上調用方法。

class GroupVerifier:
    def __init__(self):
        self.group_ids = {grp.get("pk") for grp in groups}
    def verify(self, group_id):
        # could be __call__
        return group_id in self.group_ids

我還想補充一點,它取決於API設計。 如果他們需要性能,您可以讓他們負責預先計算並提供價值。 這是例如random.choices選擇的random.choices cum_weights參數不是必需的,但它允許用戶消除性能關鍵代碼中每次調用時計算該數組的開銷。 因此,不要使用可變參數,而應將None用作默認值,並僅在傳遞的值為None時才計算該設置,否則您將假定調用者為您完成了工作。

暫無
暫無

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

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