我很好奇在程序中调用函数的相对优点是什么,使用装饰器来创建函数的有序映射,并迭代遍历该映射,而不是按照我想要的顺序直接调用函数。以下是两个产生相同结果的例子:
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()
还有一些问题:
答案 0 :(得分:4)
在我能想到的所有情况下,我更喜欢第二种(非装饰的)方法。明确命名函数是直接,明显和清晰的。考虑问一个问题“这个函数从哪里调用?”以及在每种情况下你如何回答这个问题。
装饰器中可能存在一个错误,它会默默地删除一个与另一个函数具有相同调用顺序号的函数。
答案 1 :(得分:1)
第一个允许您根据需要动态更改订单,并且还可以让您更轻松地使用外部脚本更改订单。
如果您的程序逻辑清晰简单,或者如果您的程序有一天会变得更加复杂并且装饰者将无关紧要/需要进行重大更改才能适应 - 使用第二个。< / p>
您可以在这里阅读更多常见用途的装饰品: What are some common uses for Python decorators?
但总而言之,我认为这实际上取决于您的设计以及计划目的是什么。 此外,我建议,如果选择第一种方式,编写一个更好的机制来记录订单,处理两个功能等等。这些改进可能会让装饰者有所值。
答案 2 :(得分:0)
我说第二种方法,除非你以某种方式想要调用很多函数而且懒得键入(如果你实际上这样做,你的结构可能有问题)。它不仅更具可读性,因此有助于减少不必要的错误,但它也更短。
答案 3 :(得分:0)
PEAK Rules有一些有趣的实用程序可以使用@ before,@ after修饰符和一个有趣的系统来制定规则来强制执行某些行为。
更简单的机制是分配一个“权重”。每个函数然后按加权顺序对它们进行排序 - 尽管这假定了一个函数数组。如果存在层次结构,则可以在DAG上进行拓扑排序以获得线性阵列节点。