智能地按顺序执行Python函数

时间:2014-08-04 20:38:48

标签: python decorator

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

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?
  • 工作量多于它的价值吗?
  • 如果您没有正确分配订单,是否会打开太多问题的大门?
  • 是否有更智能的设计以正确的顺序呼叫功能?

4 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:1)

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

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

您可以在这里阅读更多常见用途的装饰品: What are some common uses for Python decorators?

但总而言之,我认为这实际上取决于您的设计以及计划目的是什么。 此外,我建议,如果选择第一种方式,编写一个更好的机制来记录订单,处理两个功能等等。这些改进可能会让装饰者有所值。

答案 2 :(得分:0)

我说第二种方法,除非你以某种方式想要调用很多函数而且懒得键入(如果你实际上这样做,你的结构可能有问题)。它不仅更具可读性,因此有助于减少不必要的错误,但它也更短。

答案 3 :(得分:0)

PEAK Rules有一些有趣的实用程序可以使用@ before,@ after修饰符和一个有趣的系统来制定规则来强制执行某些行为。

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