gpt4 book ai didi

python - 如何让基于类的装饰器为实例方法工作?

转载 作者:太空宇宙 更新时间:2023-11-03 15:30:27 25 4
gpt4 key购买 nike

调用装饰器有两种方法:1)通过传递装饰器函数/类

class Foo(object):
def __init__(self):
self.x = 1

@foo_decorator
def bar(self, x):
return self.x + x

或 2) 通过传递装饰器函数/类实例的返回值。

class Foo(object):
def __init__(self):
self.x = 1

@foo_decorator("args")
def bar(self, x):
return self.x + x

问题是:鉴于我需要使用基于类的方法来实现装饰器,如何让装饰器适用于这两种情况?

此类实现的一个示例是

import functools

class FooDecorator(object):
def __init__(self, *args):
if len(args) == 1 and callable(args[0]):
self.f = args[0]
functools.update_wrapper(self, args[0])
else:
self.f = None

def __call__(self, *args, **kwargs):
if self.f is not None:
return self.f(*args, **kwargs)
else:
assert len(args) >= 1 and callable(args[0])
f = args[0]
self.f = f
functools.update_wrapper(self, f)

return self

foo_decorator = FooDecorator

但是,使用以下代码测试这个简单的实现会产生一些错误:

class Foo1(object):
def __init__(self):
self.x = 1

@foo_decorator
def bar(self, x):
return self.x + x

class Foo2(object):
def __init__(self):
self.x = 1

@foo_decorator("args")
def bar(self, x):
return self.x + x


Foos = [Foo1, Foo2]

for i in range(2):
print(Foos[i].__name__)
f = Foos[i]()
print(f.bar(10))

Traceback (most recent call last):
File "python", line 47, in <module>
File "python", line 13, in __call__
TypeError: bar() missing 1 required positional argument: 'x'

这已经在 python 2.7 和 3.5 上进行了测试。

感谢任何帮助。请注意,我已经彻底搜索了整个网络,并且已经阅读了有关该主题的以下文章:

另请注意 decorator据我所知,包不支持第二种引发装饰器的方法(预初始化装饰器对象)。

最佳答案

引用文献和来源:http://www.ianbicking.org/blog/2008/10/decorators-and-descriptors.html

类方法是(非数据)描述符。如果方法在装饰过程中被替换,则必须恢复描述符功能。

这对我在 Python3 上有效。为简单起见,未实现 kwargs

class Deco:
def __init__(self, *args):
if len(args) == 1 and callable(args[0]):
self._func = args[0]
self._dargs = None
else:
self._func = None
self._dargs = args

def __call__(self, *args):
if self._func is None:
self._func = args[0]
return self
print("decorated with: {}".format(self._dargs))
return self._func(*args)

def __get__(self, obj, type=None):
if obj is None:
return self
def bound_decorated(*args):
return self.__call__(obj, *args)
return bound_decorated

(无论如何,我更喜欢任何更简单的解决方案。)

关于python - 如何让基于类的装饰器为实例方法工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42918931/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com