Python 用于更改对象状态的装饰器
我想创建一个类在别处继承,并使用装饰器在属性中存储特定的方法 我试过下面的装饰师Python 用于更改对象状态的装饰器,python,class,inheritance,decorator,Python,Class,Inheritance,Decorator,我想创建一个类在别处继承,并使用装饰器在属性中存储特定的方法 我试过下面的装饰师 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.metho
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]
期望所有修饰函数都应用于参数,但我明白了
[1, 4, 1, 5, 73, 25, 7, 2, 26, 13, 46, 9]
而不是
[7,13,9]
基本上,我想将每个用@filtermethod
修饰的函数附加到属性self.methods
,(用self.apply\u filter
连续应用),但我就是做不到
有什么线索吗?
过滤器方法本身在创建类时被调用。因此,你需要在课堂上做一些事情
下面,我更改了您的代码,以显示这是如何工作的。我所做的就是让装饰程序用\uuu init\u subclass\uu
拾取并添加到\u方法中的变量标记它要包装的函数(作为未绑定的方法)
def过滤器方法(f):
f、 _是_filter_method=True
返回f
foo类:
定义初始子类(cls,**kwargs):
funcs=(getattr(cls,v)表示目录中的v(cls))
cls._methods=[f表示函数中的f,如果hasattr(f,“_是_filter_method”)]
def应用过滤器(自身,x):
自娱自乐的方法:
x=乐趣(自我,x)
返回x
第二类(foo):
@过滤法
def方法1(自身,x):
返回[如果i>5,则i代表x中的i]
@过滤法
def方法2(自身,x):
返回[如果i<18,则i代表x中的i]
第三类(第二类):
@过滤法
def方法1(自身,x):
返回[i=4时x中i的i]
编辑:已修复重写过滤器方法
本身在创建类时被调用。因此,你需要在课堂上做一些事情
下面,我更改了您的代码,以显示这是如何工作的。我所做的就是让装饰程序用\uuu init\u subclass\uu
拾取并添加到\u方法中的变量标记它要包装的函数(作为未绑定的方法)
def过滤器方法(f):
f、 _是_filter_method=True
返回f
foo类:
定义初始子类(cls,**kwargs):
funcs=(getattr(cls,v)表示目录中的v(cls))
cls._methods=[f表示函数中的f,如果hasattr(f,“_是_filter_method”)]
def应用过滤器(自身,x):
自娱自乐的方法:
x=乐趣(自我,x)
返回x
第二类(foo):
@过滤法
def方法1(自身,x):
返回[如果i>5,则i代表x中的i]
@过滤法
def方法2(自身,x):
返回[如果i<18,则i代表x中的i]
第三类(第二类):
@过滤法
def方法1(自身,x):
返回[i=4时x中i的i]
编辑:修复了覆盖的问题,如果运行代码并查看方法列表,您会发现它是空的。装饰器将根据定义而不是实例初始化来装饰方法。看到这种情况的一种方法是在decorator中放置一些打印,然后只运行类定义
为了实现您想要的功能,一种方法是使用类变量作为方法注册表,并将装饰器稍微更改为:
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]
您将获得:
[7, 13, 9]
如果运行代码并查看方法列表,您会发现它是空的。装饰器将根据定义而不是实例初始化来装饰方法。看到这种情况的一种方法是在decorator中放置一些打印,然后只运行类定义
为了实现您想要的功能,一种方法是使用类变量作为方法注册表,并将装饰器稍微更改为:
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]
您将获得:
[7, 13, 9]
向self.methods
添加包装方法的唯一时间是实际调用包装方法时,例如method1
或method2
。向self.methods
添加包装方法的唯一时间是实际调用包装方法时,例如method1
或method2
。谢谢。我可以用新的子类foo3(foo2)
覆盖method1
吗?用新的类foo3(foo2)
我无法正确覆盖method1
。method2
变为非活动状态,或者两种方法都不起作用all@mccandar现在就试试吧-修正了上手的问题。我可以用新的子类foo3(foo2)
覆盖method1
吗?用新的类foo3(foo2)
我无法正确覆盖method1
。method2
变为非活动状态,或者两种方法都不起作用all@mccandar现在就试试吧-修好了
[7, 13, 9]