代码之家  ›  专栏  ›  技术社区  ›  RexE

Python装饰器应该多久使用一次?

  •  3
  • RexE  · 技术社区  · 15 年前

    我最近开始试验Python装饰器(和高阶函数),因为看起来它们可能会使我的Django单元测试更简洁。e、 例如,不要写:

    def visit1():
        login()
        do_stuff()
        logout()
    

    我可以这样做

    @handle_login
    def visit1():
        do_stuff()
    

    然而,经过一些实验,我发现装饰师并不像我希望的那样简单。首先,我对在不同的示例中发现的不同的decorator语法感到困惑,直到我了解到decorator在使用时的行为非常不同 take arguments . 然后我试着装饰一个方法,最终发现它不起作用,因为我首先必须这样做 turn my decorator into a descriptor __get__ 方法在整个过程中,我不止一次地感到困惑,仍然发现调试这个“修饰”代码比Python通常要复杂得多。我现在正在重新评估我的代码中是否真的需要decorator,因为我最初的动机是节省一些输入,而不是因为有任何东西真正需要高阶函数。

    所以我的问题是:装饰师的使用应该是慷慨还是节俭?避免使用它们会更像蟒蛇吗?

    4 回复  |  直到 15 年前
        1
  •  12
  •   Alex Martelli    15 年前

    装潢师在他们的位置上是很好的,绝对不能回避——如果合适的话;-)。我认为你的问题本质上是“好的,那么什么时候?” 它们是否合适?

    在某些类的某些(但不是全部)方法周围添加一些前缀和/或后缀代码就是一个很好的例子。这都是方法吗 @thisonetoo 无休止地;-)。如果它是千载难逢的,那么就不值得重构为包装器(装饰器或其他)。在中间,有一个很大的地面,装饰者非常适合。

    这可以归结为编程的黄金法则之一——干巴巴的,因为不要重复你自己。当你看到你的代码变得重复时,你应该重构重复——装饰器是一个很好的工具,尽管它们不是唯一的(辅助方法和函数、自定义元类、生成器和其他迭代器、上下文管理器。。。 许多的 在过去几年我们添加到Python中的特性中,最好将其视为干练的助手,更容易、更流畅地排除这种或那种频繁的重复形式!)。

    如果没有重复,就不需要真正的重构,因此(特别是)就不需要真正的装饰器——在这种情况下,YAGNI(你不需要它)可以胜过DRY;-)。

        2
  •  3
  •   agiliq    15 年前

    Alex已经很好地回答了您的问题,我要添加的是decorators,使您的代码更容易理解。(有时,即使你只做了一次)。

    例如,最初,我写我的Django视图,根本不考虑授权。当我写完后,我可以看到哪些需要授权用户,只需为他们输入一个@login\u即可。

    因此,任何跟踪我的人都可以一眼看到哪些视图受身份验证保护。

    当然,它们更加干燥,到处都是。

    如果不是,则请求。用户。是否经过身份验证() 返回HttpResponseRect(..)

        3
  •  3
  •   Community CDub    7 年前

    装饰师是一种提升公共空间的方法 方面

    Aspect-Oriented Programming 支持者会告诉你,有太多共同的方面,AOP是必不可少的和核心的。事实上,你可以在这里读到关于这个话题的愚蠢辩论:

    Aspect Oriented Programming vs. Object-Oriented Programming

    AOP有几个常见的用例。您可以在这里阅读以下内容:

    Do you use AOP (Aspect Oriented Programming) in production software?

    有几个跨领域的关注点,装饰师对此很有帮助。

    • 访问控制(“安全”)身份验证、授权、权限、所有权

    • 日志记录(包括调试辅助和审核)

    • Memoization )

    很少有其他设计模式是真正跨领域的,值得一个AOP装饰。

        4
  •  0
  •   gahooa    15 年前

    如果在许多函数的开头和结尾都有相同的代码,我认为这可以证明使用装饰器增加了复杂性。

    就像为一个有很多页面的网站使用一个很好(但可能很复杂)的模板一样,它确实节省了时间并最终增加了清晰度。