如何"wrap"对象自动调用超类方法而不是重写方法?



考虑:

class A(object):
def f(self): print("A")
class B(A):
def f(self): print("B")
b = B()

我可以通过以下方式在b上致电A.f

A.f(b)

有没有一种简单的方法来"包装"b,以便wrap(b).f()调用任何fA.f

这是我的解决方案,它从最高级的基类复制方法:

import types, copy
def get_all_method_names(clazz):
return [func for func in dir(clazz) if callable(getattr(clazz, func))]
def wrap(obj):
obj = copy.copy(obj)
obj_clazz = obj.__class__
base_clazz = obj_clazz.__bases__[-1] # the one which directly inherits from object
base_methods = get_all_method_names(base_clazz) # list of all method names in base_clazz
for base_method_name in base_methods:
base_method = getattr(base_clazz, base_method_name) # get the method object
if isinstance(base_method, types.FunctionType): # skip dunder methods like __class__, __init__
setattr(obj, base_method_name, base_method) # copy it into our object
return obj
# class declaration from question here
wrapped_b = wrap(b)
wrapped_b.f(wrapped_b) # prints A, unfortunately we have to pass the self parameter explicitly
b.f() # prints B, proof that the original object is untouched

这对我来说感觉很脏,但它似乎也有效。 我不确定我会依靠这个来做任何重要的事情。

import copy
def upcast(obj, clazz):
if not isinstance(obj, clazz):  # make sure we're actually "upcasting"
raise TypeError()
wrapped = copy.copy(obj)
wrapped.__class__ = clazz
return wrapped

这导致

>>> a = A()
>>> a.f()
A
>>> b = B()
>>> b.f()
B
>>> upcast(b, A).f()
A

我在这里真正做的本质上是猴子修补b的克隆并撒谎并告诉它它实际上是一个A,所以当需要解决要调用哪个版本的f时,它会调用来自A的那个。

对象切片在 python 中不受支持,就像在 C++ 中那样(您指向的链接以 cpp 为例(。 在Python中,对象切片是一个完全不同的东西,这意味着对任何支持序列协议的对象进行切片(实现getitem((和len((方法(。 例:

A = [1,2,3,4,5,6,7,8]
print(A[1:3])

但在C++对象切片只是切断基类实例在分配给父类变量时添加的属性。

最新更新