我仍然没有掌握Python中的装饰器.
我已经开始使用很多闭包来做自定义函数和编码中的类.
例如.
class Node : def __init__(self,val,children) : self.val = val self.children = children def makeRunner(f) : def run(node) : f(node) for x in node.children : run(x) return run tree=Node(1,[Node(2,[]),Node(3,[Node(4,[]),Node(5,[])])]) def pp(n) : print "%s," % n.val printTree = makeRunner(pp) printTree(tree)
据我所知,装饰器只是用于做类似事情的不同语法.
代替
def pp(n) : print "%s," % n.val printTree = makeRunner(pp)
我会写:
@makeRunner def printTree(n) : print "%s," % n.val
这一切都是装饰者吗?或者我错过了一个根本的区别?
虽然在语法上,装饰器只是"糖",但这不是考虑它们的最佳方式.
装饰器允许您将功能编织到现有代码中,而无需实际修改它.它们允许您以声明性的方式执行此操作.
这允许您使用装饰器进行面向方面编程(AOP).因此,当您想要封装在一个地方的横切关注时,您希望使用装饰器.
典型的示例可能是日志记录,您要记录函数的入口或出口,或两者.使用装饰器相当于将建议(记录此!)应用于连接点(在方法输入或退出期间).
方法修饰是一种概念,如OOP或列表推导.正如您所指出的,它并不总是合适的,并且可能被过度使用.但是在正确的位置,它可以使代码更加模块化和分离.
您的示例是真实代码还是仅仅是示例?
如果它们是真正的代码,我认为你过度使用装饰器,可能是因为你的背景(即你习惯了其他编程语言)
def run(rootnode, func): def _run(node): # recursive internal function func(node) for x in node.children: _run(x) # recurse _run(rootnode) # initial run
此run方法废弃了makeRunner.你的例子转向:
def pp(n): print "%s," % n.val run(tree, pp)
但是,这完全忽略了发电机,所以......
class Node : def __init__(self,val,children) : self.val = val self.children = children def __iter__(self): # recursive yield self for child in self.children: for item in child: # recurse yield item def run(rootnode, func): for node in rootnode: func(node)
你的榜样仍然存在
def pp(n): print "%s," % n.val run(tree, pp)
请注意,特殊方法__iter__
允许我们使用for node in rootnode:
构造.如果您不喜欢它,只需将__iter__
方法重命名为eg walker
,并将run
循环更改为:for node in rootnode.walker():
显然,该run
函数可能是一种class Node
替代方法.
如您所见,我建议您直接使用run(tree, func)
而不是将它们绑定到名称printTree
,但您可以在装饰器中使用它们,或者您可以使用该functools.partial
函数:
printTree= functools.partial(run, func=pp)
从那以后,你会的
printTree(tree)