我想创建一个在别处继承的类,并使用装饰器将特定方法存储在属性中。
我尝试了以下装饰器
def filtermethod(f):
def wrapped(self, *args, **kwargs):
self.methods.append(f)
return f(self, *args, **kwargs)
return wrapped
并使用
定义类class foo:
def __init__(self):
self.methods = []
def apply_filter(self, x):
for fun in self.methods:
x = fun(x)
return x
class foo2(foo):
@filtermethod
def method1(self, x):
return [i for i in x if i > 5]
@filtermethod
def method2(self, x):
return [i for i in x if i < 18]
并使用以下内容测试课程
foo2().apply_filter([1, 4, 1, 5, 73, 25, 7, 2, 26, 13, 46, 9])
并希望所有修饰的函数都将应用该参数,但我明白了
[1, 4, 1, 5, 73, 25, 7, 2, 26, 13, 46, 9]
代替
[7,13,9]
基本上,我想将每个用@filtermethod
装饰的函数附加到属性self.methods
(与self.apply_filter
一起应用),但是我可以
有任何线索吗?
答案 0 :(得分:1)
filtermethod
本身在创建类时被调用。因此,您需要在课堂上做些事情。
下面,我更改了代码以显示其工作方式。我要做的就是用装饰器用__init_subclass__
提取并添加到_methods
的变量(作为无约束方法)标记包装的函数。
def filtermethod(f):
f._is_filter_method = True
return f
class foo:
def __init_subclass__(cls, **kwargs):
funcs = (getattr(cls, v) for v in dir(cls))
cls._methods = [f for f in funcs if hasattr(f, '_is_filter_method')]
def apply_filter(self, x):
for fun in self._methods:
x = fun(self, x)
return x
class foo2(foo):
@filtermethod
def method1(self, x):
return [i for i in x if i > 5]
@filtermethod
def method2(self, x):
return [i for i in x if i < 18]
class foo3(foo2):
@filtermethod
def method1(self, x):
return [i for i in x if i == 4]
编辑:固定为优先
答案 1 :(得分:1)
如果运行代码并查看方法列表,您会发现它为空。装饰器将根据定义而不是实例初始化对方法进行装饰。看到这种情况的一种方法是在装饰器中放置一些图片并仅运行类定义。
为了达到您想要的目的,一种方法是将类变量用作方法注册表,并将装饰器稍作更改:
def filtermethod(registry):
def inner(f):
registry.append(f)
def wrapped(*args, **kwargs):
return f(*args, **kwargs)
return wrapped
return inner
class foo:
methods = []
def apply_filter(self, x):
for fun in foo.methods:
x = fun(self, x)
return x
class foo2(foo):
@filtermethod(foo.methods)
def method1(self, x):
return [i for i in x if i > 5]
@filtermethod(foo.methods)
def method2(self, x):
return [i for i in x if i < 18]
请注意,self
是在apply_filter
方法中作为参数传递的。
运行时:
foo2().apply_filter([1, 4, 1, 5, 73, 25, 7, 2, 26, 13, 46, 9])
您将获得:
[7, 13, 9]