我找到了this post,其中一个函数用于从类继承:
def get_my_code(base):
class MyCode(base):
def initialize(self):
...
return MyCode
my_code = get_my_code(ParentA)
我想做类似的事情,但是有一个装饰者,比如:
@decorator(base)
class MyClass(base):
...
这可能吗?
更新
假设您有一个在整个代码中使用的类Analysis
。然后你意识到你想要使用一个包装类Transient
,它只是分析类之上的一个时间循环。如果在代码中我替换了分析类,但是Transient(Analysis)
一切都会因为期望分析类而破坏,因此它的所有属性都会破坏。问题是我不能以这种方式定义class Transient(Analysis)
,因为有很多分析类。我认为最好的方法是进行某种动态继承。现在我使用聚合将功能重定向到瞬态内的分析类。
答案 0 :(得分:0)
类装饰器实际上获取已经构建的类 - 并实例化(作为类对象)。它可以对它的dict执行更改,甚至可以将其方法与其他装饰器一起包装。
然而,这意味着该类已经设置了基础 - 这些通常不会改变。这意味着你必须在某些方面重建装饰器代码中的类。
但是,如果类的方法使用无参数super
或__class__
单元格变量,那些已经在成员函数中设置(在Python 3中与未绑定方法相同),你可以不要只创建一个新类并将这些方法设置为新类的成员。
所以,可能有一种方法,但这将是非平凡的。正如我在上面的评论中指出的那样,我想了解你希望能够实现的目标,因为可以将base
类放在类声明本身上,而不是使用它在装饰者配置上。
我已经精心设计了一个函数,如上所述,创建了一个新类,“克隆”原始函数,并可以重新构建使用__class__
或super
的所有方法:它返回新的这个类在功能上与原始的相同,但是交换了碱基。如果在装饰器中按要求使用(包括装饰器代码),它将只改变类基础。它不能处理装饰方法(除了classmethod和staticmethod),也不处理命名细节 - 例如方法的限定名或repr
。
from types import FunctionType
def change_bases(cls, bases, metaclass=type):
class Changeling(*bases, metaclass=metaclass):
def breeder(self):
__class__ #noQA
cell = Changeling.breeder.__closure__
del Changeling.breeder
Changeling.__name__ = cls.__name__
for attr_name, attr_value in cls.__dict__.items():
if isinstance(attr_value, (FunctionType, classmethod, staticmethod)):
if isinstance(attr_value, staticmethod):
func = getattr(cls, attr_name)
elif isinstance(attr_value, classmethod):
func = attr_value.__func__
else:
func = attr_value
# TODO: check if func is wrapped in decorators and recreate inner function.
# Although reaplying arbitrary decorators is not actually possible -
# it is possible to have a "prepare_for_changeling" innermost decorator
# which could be made to point to the new function.
if func.__closure__ and func.__closure__[0].cell_contents is cls:
franken_func = FunctionType(
func.__code__,
func.__globals__,
func.__name__,
func.__defaults__,
cell
)
if isinstance(attr_value, staticmethod):
func = staticmethod(franken_func)
elif isinstance(attr_value, classmethod):
func = classmethod(franken_func)
else:
func = franken_func
setattr(Changeling, attr_name, func)
continue
setattr(Changeling, attr_name, attr_value)
return Changeling
def decorator(bases):
if not isinstance(base, tuple):
bases = (bases,)
def stage2(cls):
return change_bases(cls, bases)
return stage2