gpt4 book ai didi

python - 使用闭包来装饰类的方法

转载 作者:行者123 更新时间:2023-11-28 19:23:18 25 4
gpt4 key购买 nike

<分区>

我需要生成一个类,该类将模仿另一个类的方法集并通过代理表现得像后者。例如如果 Base 是要模仿的类,而 Deleguate 是需要充当 Base 的类,则:

b = Base(args)
b.any_function()

严格等同于

d = Deleguate(b)
d.any_function()

如果 Deleguate 使用了 Base 中已经存在的函数,它不会被覆盖。这是您期望继承和方法重写的那种行为。在我正在处理的项目的上下文中,继承不是一个选项(除其他限制外,我无权访问工厂代码)。这就是让事情变得复杂的原因。

因此我决定编写一个“代理”装饰器:

import inspect

def proxy(bridge, target):
def proxyfy(cls):
for _, func in inspect.getmembers(target, predicate=inspect.ismethod):
fname = func.__name__
if fname in cls.__dict__:
print 'ignoring %s.%s' % (cls, fname)
continue
print 'adding %s.%s' % (cls, fname)
def proxy_func(self, *args, **kwargs):
print 'calling %s.%s.%s' % (cls, bridge, fname)
bridge_member = getattr(self, bridge)
return getattr(bridge_member, fname)(*args, **kwargs)
setattr(cls, fname, proxy_func)
return cls
return proxyfy

class Base(object):
def __init__(self, i):
self._i = i

def __bar(self):
print 0

def foo(self):
print self._i

def foo2(self):
print 2 * self._i


@proxy('_proxy', Base)
class Deleguate(object):
def __init__(self, base):
self._proxy = base

def foo2(self):
print 4 * self._proxy._i

d = Deleguate(Base(1))
d.__bar() # d._proxy.__bar()
d.foo() # d._proxy.foo()
d.foo2() # d.foo2()

我得到以下输出:

adding <class '__main__.Deleguate'>.__bar
ignoring <class '__main__.Deleguate'>.__init__
adding <class '__main__.Deleguate'>.foo
ignoring <class '__main__.Deleguate'>.foo2
calling <class '__main__.Deleguate'>._proxy.foo2
2
calling <class '__main__.Deleguate'>._proxy.foo2
2
4

我以为 setattr(cls, fname, proxy_func) 会分配一个新的闭包,但是参数在每个循环步骤都会被覆盖,而且只有最后一个函数的参数 foo2 被保留。因此,调用 Deleguate 的任何“生成”函数都使用 foo2 参数...

为什么闭包参数被覆盖?有没有办法生成那种代理代码?预期的输出是:

adding <class '__main__.Deleguate'>.__bar
ignoring <class '__main__.Deleguate'>.__init__
adding <class '__main__.Deleguate'>.foo
ignoring <class '__main__.Deleguate'>.foo2
calling <class '__main__.Deleguate'>._proxy.__bar
0
calling <class '__main__.Deleguate'>._proxy.foo
1
4

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com