我有一些看起来像这样的类:
class Foo:
bar = None
@baz(frob=bar)
def oof():
pass
class Rab(Foo):
bar = 'zab'
Run Code Online (Sandbox Code Playgroud)
我无法控制@baz装饰器,我需要使用bar新类的class属性Rab.但是调用Rab.oof()使用bar=None基类.
所以这里是一种奇怪/有趣的方法,你只需要修改Foo,这里的想法是创建一个新的装饰器,延迟baz装饰,直到首次使用基于类名的缓存调用函数,以便它只发生一旦.
请注意,这还包括一个虚拟实现baz,只是打印提供的frob参数,但这种方法应该可以正常工作而无需修改baz:
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()
Run Code Online (Sandbox Code Playgroud)
我还必须添加一个self参数,oof基于假设oof是一个方法,如果baz还将函数转换为静态方法,我不确定这种方法是否有效.
您可以打开闭包Foo并取出包装的函数,然后将其重新包装在派生类的装饰器中。但如果有什么方法可以实现Foo甚至baz改变它们的实现,那就更好了。
class Rab(Foo):
bar = 'zab'
oof = baz(frob=bar)(Foo.oof.func_closure[0].cell_contents)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
200 次 |
| 最近记录: |