假设我有一个基类和一个派生类,如下所示:
class A:
def foo(self):
pass
class B(A):
def foo(self):
pass
我希望 Package B
示例发出的foo
调用。不允许修改B的任何部分(我不拥有B)。
我目前拥有的:
class A:
def __init__(self):
fnames = ["foo"]
for fname in fnames:
def capture(f):
def wrapper(*args, **kwargs):
print("wrapped")
return f(*args, **kwargs)
return wrapper
meth = capture(getattr(self, fname))
bound = meth.__get__(self)
setattr(self, fname, bound)
class B(A):
def foo(self):
print("b")
o = B()
o.foo()
print(o.foo)
这和预期的一样,但是我担心这会导致内存效率低下。o.foo
是一个<bound method A.__init__.<locals>.capture.<locals>.wrapper of <__main__.B object at 0x10523ffd0>>
,看起来我必须为我创建的每个示例支付2个闭包的成本。
有没有更好的方法来做这件事?也许是基于元类的方法?
2条答案
按热度按时间li9yvcax1#
除非你打算同时运行数千个示例,否则这样做的资源使用量并不重要--与正在运行的Python应用程序所使用的其他资源相比,它是相当小的。
仅供比较:异步协程和任务是一种对象,一个人可以在一个过程中创建数千个,它只是"ok",将有类似的开销。
但是既然你已经控制了
B
的 * base * 类,有几种方法可以做到这一点,而不用求助于"猴子修补"--那将是在B创建后修改它的位置。当你必须修改一个他们不控制代码的类时,这通常是唯一的选择。当从
B
示例检索方法时,以一种懒惰的方式自动 Package 方法,甚至可以避免这种情况--而且肯定比在基类__init__
Package 更优雅:如果你事先知道你必须 Package 的方法,并且确信它们是在你控制的类的子类中实现的,这可以通过制作一个专门的
__getattribute__
方法来实现:这样,只有当要使用该方法时,它才被 Package 。至于在创建B时 Package
foo
,这会给use带来更少的资源--虽然它可以在元类中完成,但从Python 3.6开始,__init_subclass__
特殊方法可以处理它,而不需要定制元类。但是,如果代码可能会在
class C(B):
中进一步子类化B,而class C(B):
又将覆盖foo
,则这种方法可能会很棘手:如果方法使用super()
调用基类中的foo
,则 Package 器可能被多次调用。避免 Package 器中的代码运行超过一次将需要一些复杂的状态处理(但可以毫无意外地完成)。5cnsuln72#
以下@jsbueno回答
使用
types.MethodType(attr, self)
比用
因为partial没有描述符,所以返回的属性没有绑定到类示例。只需要将返回 Package 器固定到