装饰类方法-如何将实例传递给装饰器?
- 2025-02-27 09:07:00
- admin 原创
- 20
问题描述:
这是 Python 2.5,也是GAE,但这并不重要。
我有以下代码。我正在装饰 bar 中的 foo() 方法,使用该类dec_check
作为装饰器。
class dec_check(object):
def __init__(self, f):
self.func = f
def __call__(self):
print 'In dec_check.__init__()'
self.func()
class bar(object):
@dec_check
def foo(self):
print 'In bar.foo()'
b = bar()
b.foo()
当执行这个时我希望看到:
In dec_check.__init__()
In bar.foo()
但是我得到的结果TypeError: foo() takes exactly 1 argument (0 given)
是.foo()
,作为对象方法,需要self
作为参数。我猜问题是,当我执行装饰器代码时,的实例bar
实际上并不存在。
那么如何将实例传递bar
给装饰器类?
解决方案 1:
您需要将装饰器变成描述器- 通过确保其(元)类具有__get__
方法,或者更简单地使用装饰器函数而不是装饰器类(因为函数已经是描述器)。例如:
def dec_check(f):
def deco(self):
print 'In deco'
f(self)
return deco
class bar(object):
@dec_check
def foo(self):
print 'in bar.foo'
b = bar()
b.foo()
这将打印
In deco
in bar.foo
根据需要。
解决方案 2:
当一个函数足够时,Alex 的答案就足够了。但是,当你需要一个类时,你可以通过向装饰器类添加以下方法来使其工作。
def __get__(self, obj, objtype):
"""Support instance methods."""
import functools
return functools.partial(self.__call__, obj)
要理解这一点,您需要了解描述符协议。描述符协议是将事物绑定到实例的机制。它由和组成__get__
,当从实例字典中获取、设置或删除事物时,将调用它们。__set__
`__delete__`
在这种情况下,当从实例中获取事物时,我们__call__
使用 partial 将其方法的第一个参数绑定到实例。在构造类时,对于成员函数,此操作会自动完成,但对于像这样的合成成员函数,我们需要明确执行此操作。
解决方案 3:
如果您想将装饰器写成一个类,您可以这样做:
from functools import update_wrapper, partial
class MyDecorator(object):
def __init__(self, func):
update_wrapper(self, func)
self.func = func
def __get__(self, obj, objtype):
"""Support instance methods."""
return partial(self.__call__, obj)
def __call__(self, obj, *args, **kwargs):
print('Logic here')
return self.func(obj, *args, **kwargs)
my_decorator = MyDecorator
class MyClass(object):
@my_decorator
def my_method(self):
pass
相关推荐
热门文章
项目管理软件有哪些?
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理必备:盘点2024年13款好用的项目管理软件
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
热门标签
云禅道AD