我有一个类从其父类继承装饰属性。我想再添加一个decorator(@thedecorator1("yyy")
),但不重写整个方法和现有的decorator。(装饰工的顺序在某种程度上很重要,装饰工1应始终介于属性.setter以及Decorator2)
在Python3中这是可能的吗?在
from functools import wraps
class thedecorator1:
def __init__ (self, idx):
self.idx = idx
def __call__ (self, func):
@wraps(func)
def wrapped(*args, **kwargs):
print("thedecorator1", self.idx, args)
return func(*args, **kwargs)
return wrapped
def thedecorator2(func):
def _thedecorator2(self, *args, **kwargs):
print("thedecorator2",args)
return func(self, *args, **kwargs)
return _thedecorator2
class SomeClass:
"""That's te base class"""
_some_property = None
@property
@thedecorator2
def someproperty(self):
return self._some_property
@someproperty.setter
@thedecorator1("xxx")
@thedecorator2
def someproperty(self, value):
self._some_property = value
class AnotherClass(SomeClass):
"""That's what works, but I need to copy everything everytime"""
_some_property = None
@property
@thedecorator2
def someproperty(self):
return self._some_property
@someproperty.setter
@thedecorator1("yyy")
@thedecorator1("xxx")
@thedecorator2
def someproperty(self, value):
self._someproperty = value
class YetAnotherClass(SomeClass):
"""That's what I think I need"""
dosomethingsmart(target = someproperty, decorator = thedecorator1("yyy"), after=someproperty.setter)
没有办法做到这一点,因为一个装饰者并不“知道”在它之前或之后应用的任何其他装饰器。decorator不是附加到函数的额外信息;相反,当您使用decorator时,它会用修饰后的版本替换原来的函数。它不像你有一个单独的装饰器列表的函数;你只是得到了应用所有装饰器的最终结果,压缩到一个对象中,然后你就不能窥视内部并知道哪些装饰器在起作用。所以当你写这篇文章时:
现在,
SomeClass.someproperty
是一个属性对象。该属性对象包装thedecorator2
,但是property
不知道thedecorator2
;它只包装它给定的对象。您定义了一个名为someproperty
的方法,但是decorator将其包装并“掩埋”原始函数;没有通用的方法来“展开”一系列装饰器来访问原始函数或部分修饰的中间函数(例如,应用thedecorator2
而不是property
)的结果。在稍后当您定义另一个类时,您会说您想要“添加一个装饰器”。但是为了什么?您唯一可以访问的是
SomeClass.someproperty
。您定义的原始函数不可用;它被“隐藏”在decorators之下,您无法将其取出。在现在,对于一些修饰符,您可能可以恢复原来的函数。例如,
property
将其getter函数存储在其fget
属性中。但如何(或如果!)一个decorator存储原始函数是由那个decorator决定的。例如,thedecorator2
修饰符不会以任何方式公开func
。如果每个人都知道哪些装饰物是可以使用的。但这仍然要求您知道最初应用了哪些修饰符,因此它不会为您节省任何不必在AnotherClass
中复制该信息的情况。在归根结底,装潢师不会“保存”他们所装饰的最初的东西;他们只是将其压缩成他们生产的任何东西。没有通用的方法来“剥离”已装饰函数的装饰器,甚至不知道应用了哪些装饰器。因此,您不能有类似
insert_new_decorator(somefunction, after=somedecorator)
的内容,因为没有办法从装饰层中剥离出来来知道somedecorator
在堆栈中的位置。在装饰家不像衣服,你可以脱下外套,在里面换上不同的衬衫,然后再穿上原来的夹克。更确切地说,想象一下草莓蘸上巧克力,然后蘸上鲜奶油,再淋上糖霜。你不能“拆开”奶油和糖霜,在下面涂上不同的巧克力涂层。整个物体被融合成一个物体,而这个物体的层是不能被分开的。在
考虑一下这个程序:
foo是从C.foo继承get和delete函数的属性,但包装了set函数。在
^{pr2}$D
的另一个定义是:无论哪种情况,程序的输出都是:
注意,
c.foo
的赋值调用一个包装器,而对d.foo
的赋值同时调用这两个包装器。在相关问题 更多 >
编程相关推荐