How to decorate an object method?
我需要装饰一个物体的方法。它需要在运行时进行,因为应用于对象的装饰器依赖于用户在调用程序时提供的参数(argv提供的参数),因此同一个对象可以装饰3次、2次或根本不装饰。
这里是一些上下文,程序是一个解谜者,主要行为是自动找到解谜的解决方案,我的意思是自动的,不需要用户干预。这里是装饰的地方,我想画一张执行过程中发生的事情的图表,但我只想在使用
以下是我的尝试:
1 2 3 4 5 6 7 8 9 | class GraphDecorator(object): def __init__(self, wrappee): self.wrappee = wrappee def method(self): # do my stuff here self.wrappee.method() # do more of stuff here def __getattr__(self,attr): return getattr(self.wrappee,attr) |
为什么它不起作用:它不起作用,因为我构建应用程序的方式,当调用decorator类中不存在的方法时,它感觉回到了decorated类的实现中,问题是应用程序总是开始调用不需要修饰的方法
1 2 3 4 5 6 7 8 9 10 | # method responsible to replace the undecorated form by the decorated one def graphDecorator(obj): old_method = obj.method def method(self): # do my stuff here old_method() # do more of my stuff setattr(obj,'method',method) # replace with the decorated form |
这就是我的问题,当调用修饰形式时,它没有接收到
问题是我不能用func(self)作为方法。原因是setAttr()方法没有绑定函数,并且函数的行为类似于一个静态方法(而不是类方法),多亏了Python的内省性,我能够想出这个解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 | def decorator(obj): old_func = obj.func # can't call 'by name' because of recursion def decorated_func(self): # do my stuff here old_func() # does not need pass obj # do some othere stuff here # here is the magic, this get the type of a 'normal method' of a class method = type(obj.func) # this bounds the method to the object, so self is passed by default obj.func = method(decorated_func, obj) |
我认为这是在运行时修饰对象方法的最佳方法,不过最好找到一种直接调用
"它需要在运行时,因为应用于对象的装饰器取决于用户在调用程序时提供的参数。"
不使用装修工。装饰器只是包装器的语法支持,您也可以使用普通的函数/方法调用。
I need to decorate a object's method. It needs to be at runtime because the decorators applied on the object depends on the arguments that the user gave when calling the program (arguments supplied with argv), so a same object could be decorated 3 times, 2 times, or not be decorated at all.
不幸的是,上面的内容是不正确的,您试图做的是不必要的。您可以在运行时这样做。例子:
1 2 3 4 5 6 7 8 9 10 | import sys args = sys.argv[1:] class MyClass(object): pass if args[0]=='--decorateWithFoo': MyClass = decoratorFoo(MyClass) if args[1]=='--decorateWithBar' MyClass = decoratorBar(MyClass) |
句法:
1 2 | @deco define something |
与以下内容相同:
1 2 | define something something = deco(something) |
你也可以做一家装饰工厂。
您可能希望使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class GraphDecorator(object): def __init__(self, wrappee): self.__wrappee = wrappee def method(self): # do my stuff here self.wrappe.method() # do more of stuff here def __getattribute__(self, name): try: wrappee = object.__getattribute__(self,"_GraphDecorator__wrappee") return getattr(wrappee, name) except AttributeError: return object.__getattribute__(self, name) |