python 函数修饰器 父类_反射-Python装饰器使函数忘记它属于一个类

文章介绍了一个解决方法修饰器(method_decorator)的问题,它能够适用于普通函数、静态方法和类方法,并且在类中正确隐藏装饰器的痕迹。通过unit test覆盖了不同类型的用例。使用方法包括安装method_decorator库并导入,然后创建自定义装饰器。文中还展示了method_decorator类的实现细节,强调了__getattribute__方法在隐藏装饰器痕迹中的作用。
摘要由CSDN通过智能技术生成

这里提出的想法很棒,但是有一些缺点:

method_decorator和@wraps不适合普通函数和静态方法。

method_decorator必须在一个类中,该类被@wraps拒绝。

method_decorator本身应该更好地隐藏痕迹。

因此,我结合了此页面中的一些想法,链接,文档和我自己的头脑,

最终找到了一个解决方案,它没有上述三个缺点。

结果,method_decorator:

知道装饰方法绑定到的类。

通过比method_decorator更正确地回答系统属性来隐藏装饰器跟踪。

单元测试涵盖了绑定的未绑定实例方法,类方法,静态方法和纯函数。

用法:

pip install method_decorator

from method_decorator import method_decorator

class my_decorator(method_decorator):

# ...

有关用法的详细信息,请参见完整的单元测试。

这只是method_decorator类的代码:

class method_decorator(object):

def __init__(self, func, obj=None, cls=None, method_type='function'):

# These defaults are OK for plain functions

# and will be changed by __get__() for methods once a method is dot-referenced.

self.func, self.obj, self.cls, self.method_type = func, obj, cls, method_type

def __get__(self, obj=None, cls=None):

# It is executed when decorated func is referenced as a method: cls.func or obj.func.

if self.obj == obj and self.cls == cls:

return self # Use the same instance that is already processed by previous call to this __get__().

method_type = (

'staticmethod' if isinstance(self.func, staticmethod) else

'classmethod' if isinstance(self.func, classmethod) else

'instancemethod'

# No branch for plain function - correct method_type for it is already set in __init__() defaults.

)

return object.__getattribute__(self, '__class__')( # Use specialized method_decorator (or descendant) instance, don't change current instance attributes - it leads to conflicts.

self.func.__get__(obj, cls), obj, cls, method_type) # Use bound or unbound method with this underlying func.

def __call__(self, *args, **kwargs):

return self.func(*args, **kwargs)

def __getattribute__(self, attr_name): # Hiding traces of decoration.

if attr_name in ('__init__', '__get__', '__call__', '__getattribute__', 'func', 'obj', 'cls', 'method_type'): # Our known names. '__class__' is not included because is used only with explicit object.__getattribute__().

return object.__getattribute__(self, attr_name) # Stopping recursion.

# All other attr_names, including auto-defined by system in self, are searched in decorated self.func, e.g.: __module__, __class__, __name__, __doc__, im_*, func_*, etc.

return getattr(self.func, attr_name) # Raises correct AttributeError if name is not found in decorated self.func.

def __repr__(self): # Special case: __repr__ ignores __getattribute__.

return self.func.__repr__()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值