python-使用类作为方法装饰器
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python-使用类作为方法装饰器,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3346字,纯文字阅读大概需要5分钟。
内容图文
![python-使用类作为方法装饰器](/upload/InfoBanner/zyjiaocheng/685/a156ef779db94e9190964409235f101e.jpg)
这个问题已经在这里有了答案: > How can I decorate an instance method with a decorator class? 3个
虽然有plenty of resources about using classes as decorators,但我找不到能够解决装饰方法问题的任何东西.这个问题的目的是解决这个问题.我将发布自己的解决方案,但是当然也邀请其他所有人发布他们的解决方案.
为什么“标准”实施不起作用
标准装饰器类实现的问题是python不会创建装饰函数的绑定方法:
class Deco:
def __init__(self, func):
self.func= func
def __call__(self, *args):
self.func(*args)
class Class:
@Deco
def hello(self):
print('hello world')
Class().hello() # throws TypeError: hello() missing 1 required positional argument: 'self'
方法装饰者需要克服这一障碍.
要求
以前面示例中的类为例,预期将完成以下工作:
>>> i= Class()
>>> i.hello()
hello world
>>> i.hello
<__main__.Deco object at 0x7f4ae8b518d0>
>>> Class.hello is Class().hello
False
>>> Class().hello is Class().hello
False
>>> i.hello is i.hello
True
理想情况下,函数的__doc__和签名以及类似的属性也应保留.
解决方法:
通常,当以some_instance.some_method()访问方法时,python的descriptor protocol会插入并调用some_method .__ get __(),这将返回绑定的方法.但是,由于该方法已替换为Deco类的实例,因此不会发生-因为Deco不是描述符.为了使Deco正常工作,它必须实现__get__方法,该方法返回自身的绑定副本.
实作
这是基本的“不执行任何操作”修饰符类:
import inspect
import functools
from copy import copy
class 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
这样的实现使我们可以在方法和函数上使用装饰器,因此我认为应将其视为良好实践.
内容总结
以上是互联网集市为您收集整理的python-使用类作为方法装饰器全部内容,希望文章能够帮你解决python-使用类作为方法装饰器所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。