【问题标题】:Intelligently Execute Python Functions in Order智能按顺序执行 Python 函数
【发布时间】:2014-09-27 10:13:11
【问题描述】:

我很好奇使用装饰器在程序中调用函数以创建函数的有序映射并遍历该映射,而不是按照我想要的顺序直接调用函数,有什么相对优点。以下是两个产生相同结果的示例:

PROCESS_MAP = {}


def register(call_order):
    def decorator(process_func):
        PROCESS_MAP[call_order] = process_func
        return process_func
    return decorator


@register(99)
def func3():
    print 'last function'


@register(1)
def func0():
    print 'first function'


@register(50)
def func1():
    print 'middle function'


def main():
    for func in sorted(PROCESS_MAP):
        foo = PROCESS_MAP[func]
        foo()

if __name__ == '__main__':
    main()

打印出来:

first function
middle function
last function

这是否比执行以下操作更好?

def func2():
    print 'last function'


def func0():
    print 'first function'


def func1():
    print 'middle function'


def main():
    func0()
    func1()
    func2()

if __name__ == '__main__':
    main()

还有一些问题:

  • 更 Pythonic?
  • 工作量过大?
  • 如果您没有正确分配订单,是否会引发太多问题?
  • 是否有更智能的设计来以正确的顺序调用函数?

【问题讨论】:

  • 这是一种使用装饰器的非常聪明的方式,但我认为它会使您的程序逻辑更难遵循。
  • 如果函数必须始终以相同的顺序一起调用,这表明它们就像一个长函数。

标签: python decorator


【解决方案1】:

第一个可以让您根据需要动态更改订单,并且还可以让您更轻松地使用外部脚本更改订单。

如果您的程序逻辑清晰简单,或者您的程序有一天会变得更加复杂,而装饰器将变得无关紧要/需要进行重大更改才能适应第二个。

您可以在此处了解更多常见的装饰品: What are some common uses for Python decorators?

但总而言之,我想说这真的取决于您的设计以及程序的目的是什么。 此外,我建议,如果选择第一种方式,编写一个更好的机制来记录订单、处理两个函数等等。这些改进可能会让装饰器物有所值。

【讨论】:

    【解决方案2】:

    PEAK Rules 有一些有趣的实用程序,包括 @before、@after 装饰器和用于制定规则以强制执行某些行为的有趣系统。

    一个更简单的机制是为每个函数分配一个“权重”,然后按加权顺序对它们进行排序——尽管这假设一个函数数组。如果存在层次结构,您可以对 DAG 进行拓扑排序以获得节点的线性数组。

    【讨论】:

      【解决方案3】:

      我说的是第二种方法,除非你想调用很多函数并且懒得输入(如果你真的这样做,你的结构可能有问题)。它不仅更具可读性,从而有助于减少不必要的错误,而且更短。

      【讨论】:

        【解决方案4】:

        在我能想到的所有情况下,我都更喜欢第二种(非装饰)方法。明确地命名函数是直接、明显和清晰的。考虑问“这个函数是从哪里调用的?”这个问题。以及在每种情况下您如何回答。

        装饰器中可能存在一个错误,它会静默删除与不同函数具有相同调用顺序号的函数。

        【讨论】:

        • 如果您想根据参数调整函数顺序,或者如果您经常更改顺序并且想使用脚本,那么第一个确实会给您带来优势
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-07-29
        • 2017-10-02
        • 1970-01-01
        • 1970-01-01
        • 2015-11-09
        • 2016-05-17
        • 2020-08-22
        相关资源
        最近更新 更多