使用类作为方法装饰器

使用类作为方法装饰器,第1张

使用类作为方法装饰

通常,当方法访问为时

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

这样的实现使我们可以在方法和函数上使用装饰器,因此我认为应该将其视为良好实践。



欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5674375.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存