用于去抖动(包括函数参数)的 Python 装饰器

2023-11-21

如何在 python 中编写一个去抖装饰器,它不仅对调用的函数进行去抖,而且对所使用的函数参数/函数参数组合进行去抖?

去抖意味着在给定的时间范围内抑制对函数的调用,假设您在 1 秒内调用一个函数 100 次,但您只想允许该函数每 10 秒运行一次,去抖装饰函数将在 10 秒后运行该函数一次如果没有进行新的函数调用,则为最后一次函数调用。在这里我问的是如何使用特定的函数参数来消除函数调用的反跳。

一个例子是取消对人员对象的昂贵更新,例如:

@debounce(seconds=10)
def update_person(person_id):
    # time consuming, expensive op
    print('>>Updated person {}'.format(person_id))

然后对函数进行去抖动 - 包括函数参数:

update_person(person_id=144)
update_person(person_id=144)
update_person(person_id=144)
>>Updated person 144

update_person(person_id=144)
update_person(person_id=355)
>>Updated person 144
>>Updated person 355

因此,使用相同的 person_id 调用函数 update_person 将被抑制(去抖),直到 10 秒的去抖间隔过去,而没有对具有相同 person_id 的函数进行新的调用。

有一些去抖装饰器,但没有一个包含函数参数,例如:https://gist.github.com/walkermatt/2871026

我通过函数和参数做了一个类似的节流装饰器:

def throttle(s, keep=60):

    def decorate(f):

        caller = {}

        def wrapped(*args, **kwargs):
            nonlocal caller

            called_args = '{}'.format(*args)
            t_ = time.time()

            if caller.get(called_args, None) is None or t_ - caller.get(called_args, 0) >= s:
                result = f(*args, **kwargs)

                caller = {key: val for key, val in caller.items() if t_ - val > keep}
                caller[called_args] = t_
                return result

            # Keep only calls > keep
            caller = {key: val for key, val in caller.items() if t_ - val > keep}
            caller[called_args] = t_

        return wrapped

    return decorate

主要要点是它将函数参数保留在 call[used args] 中

另请参阅节流阀和防抖之间的区别:http://demo.nimius.net/debounce_throttle/

Update:

在对上面的节流阀装饰器和要点中的 threading.Timer 示例进行一些修改之后,我实际上认为这应该有效:

from threading import Timer
from inspect import signature
import time


def debounce(wait):
    def decorator(fn):
        sig = signature(fn)
        caller = {}

        def debounced(*args, **kwargs):
            nonlocal caller

            try:
                bound_args = sig.bind(*args, **kwargs)
                bound_args.apply_defaults()
                called_args = fn.__name__ + str(dict(bound_args.arguments))
            except:
                called_args = ''

            t_ = time.time()

            def call_it(key):
                try:
                    # always remove on call
                    caller.pop(key)
                except:
                    pass

                fn(*args, **kwargs)

            try:
                # Always try to cancel timer
                caller[called_args].cancel()
            except:
                pass

            caller[called_args] = Timer(wait, call_it, [called_args])
            caller[called_args].start()

        return debounced

    return decorator

在偶然发现之后,我也有同样的需要为个人项目构建去抖注释相同的要点/讨论你有,我最终得到了以下解决方案:

import threading
def debounce(wait_time):
    """
    Decorator that will debounce a function so that it is called after wait_time seconds
    If it is called multiple times, will wait for the last call to be debounced and run only this one.
    """

    def decorator(function):
        def debounced(*args, **kwargs):
            def call_function():
                debounced._timer = None
                return function(*args, **kwargs)
            # if we already have a call to the function currently waiting to be executed, reset the timer
            if debounced._timer is not None:
                debounced._timer.cancel()

            # after wait_time, call the function provided to the decorator with its arguments
            debounced._timer = threading.Timer(wait_time, call_function)
            debounced._timer.start()

        debounced._timer = None
        return debounced

    return decorator

我创建了一个开源项目来提供诸如去抖、节流、过滤等功能...作为装饰器,非常欢迎贡献来改​​进我为这些装饰器提供的解决方案/添加其他有用的装饰器:装饰器操作存储库

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用于去抖动(包括函数参数)的 Python 装饰器 的相关文章

随机推荐

  • SQL 的 DISTINCT 子句如何工作?

    我正在寻找有关 DISTINCT 子句在 SQL SQL Server 2008 如果这有影响的话 中如何在连接多个表的查询上工作的答案 我的意思是 SQL 引擎如何处理带有 DISTINCT 子句的查询 我问这个问题的原因是 我经验丰富的
  • pandas 日期列减法

    我有一个像这样的熊猫数据框 created time reached time 2016 01 02 12 57 44 14 20 22 2016 01 02 12 57 44 13 01 38 2016 01 03 10 38 51 12
  • 如何添加确认对话框

    我想在编辑行之前添加确认对话框 或者如何在执行任何操作之前提示用户确认 我应该在下面的代码中使用哪个对话框
  • 在 TabNavigator 中隐藏标签 - ReactNavigation

    如何隐藏标签TabNavigator并仅显示icons 如果我执行以下操作 const Tabs TabNavigator Home screen MainHome navigationOptions navigation gt title
  • 有没有办法反转 c 中的 crypt() ?

    不确定这是否可行 但我希望能够从字符串开始 然后弄清楚输入必须是什么crypt为了得到这个字符串 或者也许这是不可能的 但这就是事情的全部目的 是的 我正在尝试的代码中有盐 根据设计意图 crypt 是一种单向哈希 正如每个人所说 这意味着
  • NHibernate - 脱水属性值时出错

    我在更新期间提交时收到错误错误脱水属性值 我已经搜索过了 它看起来类似于NHibernate 脱水属性时出错 这到底是什么 唯一的区别是 NHibernate 在提到的问题中抱怨无法解决财产问题 IssuingOffice 的值已存在于数据
  • 带有 HEAD 请求的内容长度标头?

    The http规范说关于HEAD要求 HEAD 方法与 GET 相同 只是服务器不得在响应中返回消息正文 响应 HEAD 请求的 HTTP 标头中包含的元信息应该与响应 GET 请求而发送的信息相同 如果响应HEAD请求包含一个Conte
  • 为什么泛型方法的定义中有时会省略返回类型之前的尖括号

    我正在阅读 Effective Java 第 5 章有关泛型的内容 特别是有关首选泛型方法的内容 我注意到有时方法声明中返回类型之前的类型参数 尖括号之间 有时会被省略 类似的例子还有很多 比如第二版第135页 public void po
  • 为什么我的 Rust 线​​程没有并行运行?

    我希望启动 X 线程 这将向代码中的指定服务器发出 X 请求 目前 我的应用程序正在等待每个线程和 X 请求完成 然后再启动下一个线程 我该如何去做这个异步 extern crate hyper extern crate time use
  • iOS 屏幕锁定时背景音频停止

    我正在尝试让我的音频应用程序在后台播放 到目前为止 我将 应用程序播放音频 添加到 info plist 中的 所需背景模式 中 并在启动声音生成器之前添加了以下代码 AudioSessionInitialize NULL kCFRunLo
  • 在 Android NDK 项目中包含 ICU

    我用 C 构建了一个库 希望使用 NDK 将其包含在我的 Android 应用程序中 但是 我的图书馆需要使用 ICU4C 我一直在尝试为 Android 编译 ICU 并且我在 SO 上查看了很多问题 但我仍然无法将 ICU 编译为 An
  • Xcode 4.3 如何使用 SVN 合并两个开发人员的故事板更改?

    我遇到一个问题 一个项目有多个开发人员处理同一个故事板文件 当开发人员将控制器添加到他们自己的故事板版本时 需要合并文件 当我在合并过程中查看纯文本格式的故事板时 我无法理解我应该接受哪些更改以及按什么顺序接受 是否有某种关于如何从同一故事
  • MEF = 可能会感到沮丧?

    UPDATE 当我尝试让 MEF 在我的应用程序中工作时 我遇到了越来越多的地方 我只是不明白为什么它没有在我期望的时候自动创建我的库 我认为这一切都回到了 Reed 所说的需要 MEF 来创造一切 现在 我有一个 XML 读取器类需要使用
  • 仅使用小于运算符测试等效性?

    假设我有两个 T 类型的文字 我想测试它们是否相等 但类型 T 仅实现了 小于 运算符 我怎样才能在 C 中测试这个 您可以通过几个 小于 比较和一个否定来模拟相等运算符 if t1 lt t2 t2 lt t1 printf t1 and
  • 以 tidyeval 方式删除列

    我想使用 dplyr gt 0 7 删除列向量 library dplyr data mtcars rem cols lt c wt qsec vs am gear carb head select mtcars paste0 rem co
  • 为什么此 WPF RoutedCommand 绑定上下文菜单项被禁用?

    我目前仍在摸索 WPF 并且无法弄清楚为什么此上下文菜单项被禁用
  • IdentityServer4 与外部提供商关联失败错误

    我正在尝试将 Ping Federate 集成为我的 IdentityServer4 实例的外部 OIDC 提供商 当我启动外部登录流程时 出现以下错误 System Exception Correlation failed at Micr
  • 在 .NET (C#) Web 服务中本机返回 XML?

    我意识到 NET 中的 SOAP Web 服务返回 Web 方法返回的任何对象的 XML 表示形式 但如果我想返回 XML 格式的数据 存储它的最佳对象是什么 我正在使用answer to 这个问题编写我的 XML 代码如下 XmlWrit
  • 使用 CsvHelper 可以将空格转换为可为空吗?

    我有一些非常蹩脚的 Csv 文件需要解析 我正在使用 CsvHelper 它运行得很棒 除了我有一些带有空格的行 通常我有一个双行 File 文本 SomeDouble 更多文本 好 1 23 好 不好 不好 如果我尝试将其映射到 publ
  • 用于去抖动(包括函数参数)的 Python 装饰器

    如何在 python 中编写一个去抖装饰器 它不仅对调用的函数进行去抖 而且对所使用的函数参数 函数参数组合进行去抖 去抖意味着在给定的时间范围内抑制对函数的调用 假设您在 1 秒内调用一个函数 100 次 但您只想允许该函数每 10 秒运