import collections import collections.abc import inspect import sys _REGISTRY = collections.defaultdict(dict) def register(kind, name):#注册类,kind为类的类型,name为类名 kind_registry = _REGISTRY[kind] def decorator(obj): if name in kind_registry: raise LookupError(f'{name} already registered as kind {kind}') kind_registry[name] = obj return obj return decorator def lookup(kind, name):#根据类的类型和类名找到相应的类 if isinstance(name, collections.abc.Mapping): name = name['name'] if kind not in _REGISTRY: raise KeyError(f'Nothing registered under "{kind}"') return _REGISTRY[kind][name] def construct(kind, config, unused_keys=(), **kwargs):#对类进行实例化。 return instantiate( lookup(kind, config), config, unused_keys + ('name',), **kwargs) def instantiate(callable, config, unused_keys=(), **kwargs):#用途初始化类(callable类名,config初始化参数,kwargs其他参数) merged = {**config, **kwargs} signature = inspect.signature(callable.__init__) for name, param in signature.parameters.items(): if param.kind in (inspect.Parameter.POSITIONAL_ONLY, inspect.Parameter.VAR_POSITIONAL): raise ValueError(f'Unsupported kind for param {name}: {param.kind}') if any(param.kind == inspect.Parameter.VAR_KEYWORD for param in signature.parameters.values()): return callable(**merged) missing = {} for key in list(merged.keys()): if key not in signature.parameters: if key not in unused_keys: missing[key] = merged[key] merged.pop(key) if missing: print(f'WARNING {callable}: superfluous {missing}', file=sys.stderr) return callable(**merged) if __name__ == '__main__': @register('a_class','a_ins') class A(): def __init__(self,a,b,**kwargs): self.a = a self.b = b self.c = kwargs print('_REGISTRY', _REGISTRY) print('lookup', lookup('a_class',{'name':'a_ins'})) config = {'name':'a_ins','a':1,'b':2,'c':3} print('construct', construct('a_class', config)) a_instance = construct('a_class', config) print(a_instance.a) print(a_instance.c)
打印:
_REGISTRY defaultdict(<class 'dict'>, {'a_class': {'a_ins': <class '__main__.A'>}})
lookup <class '__main__.A'>
construct <__main__.A object at 0x7f1d08e60590>
1
{'name': 'a_ins', 'c': 3}