通常,当方法访问为时
some_instance.some_method(),python的描述符协议会加入并调用
some_method.__get__(),这会返回绑定的方法。但是,由于该方法已被
Deco类的实例替换,因此不会发生-
因为
Deco它不是描述符。为了
Deco按预期进行工作,它必须实现一个
__get__返回自身绑定副本的方法。实作
这是基本的“不执行任何 *** 作”修饰符类:
import inspectimport functoolsfrom copy import copyclass Deco(object): def __init__(self, func): self.__self__ = None # "__self__" is also used by bound methods self.__wrapped__ = func functools.update_wrapper(self, func) def __call__(self, *args, **kwargs): # if bound to an object, pass it as the first argument if self.__self__ is not None: args = (self.__self__,) + args #== change the following line to make the decorator do something == return self.__wrapped__(*args, **kwargs) def __get__(self, instance, owner): if instance is None: return self # create a bound copy bound = copy(self) bound.__self__ = instance # update __doc__ and similar attributes functools.update_wrapper(bound, self.__wrapped__) # add the bound instance to the object's dict so that # __get__ won't be called a 2nd time setattr(instance, self.__wrapped__.__name__, bound) return bound
要使装饰器执行某些 *** 作,请在
__call__方法中添加代码。
这是一个带有参数的参数:
class DecoWithArgs(object): #== change the constructor's parameters to fit your needs == def __init__(self, *args): self.args = args self.__wrapped__ = None self.__self__ = None def __call__(self, *args, **kwargs): if self.__wrapped__ is None: return self.__wrap(*args, **kwargs) else: return self.__call_wrapped_function(*args, **kwargs) def __wrap(self, func): # update __doc__ and similar attributes functools.update_wrapper(self, func) return self def __call_wrapped_function(self, *args, **kwargs): # if bound to an object, pass it as the first argument if self.__self__ is not None: args = (self.__self__,) + args #== change the following line to make the decorator do something == return self.__wrapped__(*args, **kwargs) def __get__(self, instance, owner): if instance is None: return self # create a bound copy of this object bound = copy(self) bound.__self__ = instance bound.__wrap(self.__wrapped__) # add the bound decorator to the object's dict so that # __get__ won't be called a 2nd time setattr(instance, self.__wrapped__.__name__, bound) return bound
这样的实现使我们可以在方法和函数上使用装饰器,因此我认为应该将其视为良好实践。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)