在Python包的设置中创建用户定义类的实例



Python包定义了一个基类,用户应该从中派生子类。此外,包需要在不事先知道可能的子类的情况下创建这些实例。我可以通过__init_subclass__实现这一点吗?

具体来说,我希望做这样的事情:

class BaseClass(ABC):
_registry = {}
_class_signature = None
@classmethod
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
if cls._class_signature is None:
raise KeyError('Missing signature')
elif cls._class_signature in cls._registry :
raise KeyError('Conflict in signature')
else:
cls._registry[cls._class_signature] = cls
@classmethod
def get_class_registry(cls):
return cls._registry
def __init__(self, params):
pass

,其中所有类都记录在_registry中。包的用户将创建从这个派生的子类(子类必须有自己的签名,否则会抛出)。同时,在包的另一个模块中,我希望有能力使用签名和注册字典一起创建任何派生类的实例,而不需要if…其他结构,例如(假设'sig1'是某个派生类的唯一签名)

new_instance = BaseClass(SignalBase._registry()['sig1'])

这能做到吗?

要回答我自己的问题,诀窍是将__new____init_subclass__的力量结合起来:

class BaseClass(ABC):
_registry = {}
_class_signature = None
@classmethod
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
if cls._class_signature is None:
raise KeyError('Missing signature')
elif cls._class_signature in cls._registry :
raise KeyError('Conflict in signature')
else:
cls._registry[cls._class_signature] = cls
@classmethod
def get_class_registry(cls):
return cls._registry
def __new__(cls, input_str, input_float):
my_obj = super().__new__(cls.get_class_registry()[input_str])
my_obj.my_float = input_float
return my_obj
class SubClass1(BaseClass):
_signal_signature = 'SubClass1'
def __init__(self, input_str, input_float):
pass
def __new__(cls, input_float):
pass
def id_yourself(self):
print('1')

则可以通过

创建子类对象
obj1 = BaseClass('SubClass1', 1.0)
obj1.id_yourself()

将正确返回1作为输出。

最新更新