[英]dynamic inheritance in Python through a decorator
我發現這篇文章中使用了一個函數來繼承一個類:
def get_my_code(base):
class MyCode(base):
def initialize(self):
...
return MyCode
my_code = get_my_code(ParentA)
我想做類似的事情,但是要用一個裝飾器,例如:
@decorator(base)
class MyClass(base):
...
這可能嗎?
UPDATE
假設您有一個在整個代碼中都使用的Analysis
類。 然后,您意識到要使用包裝類Transient
,該包裝類只是分析類頂部的時間循環。 如果在代碼中我替換了分析類,但是Transient(Analysis)
一切都中斷了,因為需要一個分析類,因此也需要其所有屬性。 問題是我不能僅僅以這種方式定義class Transient(Analysis)
,因為有很多分析類。 我認為最好的方法是進行某種動態繼承。 現在,我使用聚合將功能重定向到瞬態內部的分析類。
一個類裝飾器實際上獲取已經構建的類-並實例化(作為類對象)。 它可以對字典進行更改,甚至可以將其方法與其他裝飾器包裝在一起。
但是,這意味着該類已經設置了基數-並且這些基數通常無法更改。 這意味着您必須在裝飾器代碼中重新構建類。
但是,如果類的方法使用無參數的super
或__class__
單元格變量,則這些變量已在成員函數中設置(在Python 3中與未綁定方法相同),您不能只是創建一個新類並設置這些方法作為新成員的成員。
因此,也許有一種方法,但這將是不平凡的。 正如我在上面的評論中指出的那樣,我想了解您希望通過此方法實現什么,因為可以將base
類放在類聲明本身上,而不是在裝飾器配置上使用它。
我精心設計了一個函數,如上所述,它創建了一個新類,“克隆”原始類,並可以重建使用__class__
或super
所有方法:它返回的新類在功能上與原始類相同,但是與基地交換。 如果按要求在裝飾器中使用(包括裝飾器代碼),它將僅更改類的基數。 它不能處理修飾的方法(除classmethod和staticmethod之外),並且不關心命名細節-例如方法的qualname或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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.