2024-06-15 06:00:44 发布
网友
我有些课看起来像这样:
class Foo: bar = None @baz(frob=bar) def oof(): pass class Rab(Foo): bar = 'zab'
我不能控制@baz修饰符,我需要使用新类Rab的class属性bar。但是调用Rab.oof()使用基类的bar=None。在
@baz
Rab
bar
Rab.oof()
bar=None
您可以从Foo展开闭包并拉出包装好的函数,然后在派生类的decorator中重新包装它。但是如果有任何方法可以在Foo或者甚至baz来更改它们的实现,那就更好了。在
Foo
baz
class Rab(Foo): bar = 'zab' oof = baz(frob=bar)(Foo.oof.func_closure[0].cell_contents)
所以这里有一种奇怪的/有趣的方法,你只需要修改Foo,这里的想法是创建一个新的decorator来延迟baz修饰,直到函数第一次被调用时使用基于类名的缓存,这样它只发生一次。在
请注意,这还包括baz的一个伪实现,它只打印提供的frob参数,但是这种方法应该可以正常工作,而不需要修改baz:
frob
def baz(frob): def deco(func): def wrapped(*args, **kwargs): print('frob:', frob) return func(*args, **kwargs) return wrapped return deco def newdeco(func): def wrapped(self, *args, **kwargs): if not hasattr(wrapped, 'cache'): wrapped.cache = {} cls = self.__class__.__name__ if cls not in wrapped.cache: wrapped.cache[cls] = baz(frob=getattr(self.__class__, 'bar'))(func) wrapped.cache[cls](self, *args, **kwargs) return wrapped class Foo: bar = None @newdeco def oof(self): pass class Rab(Foo): bar = 'zab' f = Foo() f.oof() r = Rab() r.oof()
我还必须在假设oof是一个方法的基础上,向oof添加一个self参数,如果{}也将函数转换为staticmethod,我不确定这种方法是否有效。在
oof
self
您可以保留oof的未修饰版本,我们将其称为_oof_raw,并在子类定义中重新包装它。为了保持未修饰的版本,您需要“手动”修饰,即不使用@语法糖。在
_oof_raw
@
class Foo: bar = None def _oof_raw(self): pass oof = baz(frob=bar)(_oof_raw) class Rab(Foo): bar = 'zab' oof = baz(frob=bar)(Foo._oof_raw)
您可以从
Foo
展开闭包并拉出包装好的函数,然后在派生类的decorator中重新包装它。但是如果有任何方法可以在Foo
或者甚至baz
来更改它们的实现,那就更好了。在所以这里有一种奇怪的/有趣的方法,你只需要修改
Foo
,这里的想法是创建一个新的decorator来延迟baz
修饰,直到函数第一次被调用时使用基于类名的缓存,这样它只发生一次。在请注意,这还包括
baz
的一个伪实现,它只打印提供的frob
参数,但是这种方法应该可以正常工作,而不需要修改baz
:我还必须在假设}也将函数转换为staticmethod,我不确定这种方法是否有效。在
oof
是一个方法的基础上,向oof
添加一个self
参数,如果{您可以保留
oof
的未修饰版本,我们将其称为_oof_raw
,并在子类定义中重新包装它。为了保持未修饰的版本,您需要“手动”修饰,即不使用@
语法糖。在相关问题 更多 >
编程相关推荐