|
|
|
|
|
|
|
|
import inspect |
|
|
|
|
|
|
|
|
class ParamsSingleton(object): |
|
|
"""根据传入的参数不同而创建单例. |
|
|
由于参数中可能包含字典, 如果转字符串的话, 字典的 key 是无序的. |
|
|
所以用了列表而不是字典来存实例. """ |
|
|
__instance = list() |
|
|
_initialized = False |
|
|
|
|
|
def __new__(cls, *args, **kwargs): |
|
|
kwargs = cls.to_kwargs(*args, **kwargs) |
|
|
kwargs['cls'] = cls |
|
|
|
|
|
for obj, params in cls.__instance: |
|
|
if params == kwargs: |
|
|
return obj |
|
|
|
|
|
obj = super().__new__(cls) |
|
|
|
|
|
|
|
|
obj.kwargs = kwargs |
|
|
cls.__instance.append((obj, kwargs)) |
|
|
return obj |
|
|
|
|
|
@classmethod |
|
|
def get_all_instance(cls) -> list: |
|
|
return cls.__instance |
|
|
|
|
|
@classmethod |
|
|
def to_kwargs(cls, *args, **kwargs): |
|
|
"""将传入 __init__ 的参数全部转为 key-value 字典的关键字参数""" |
|
|
|
|
|
|
|
|
argvalues = inspect.getargvalues(inspect.currentframe()) |
|
|
args = list(argvalues.locals['args']) |
|
|
kwargs = argvalues.locals['kwargs'] |
|
|
for k, v in argvalues.locals.items(): |
|
|
if k in ('cls', 'args', 'kwargs'): |
|
|
continue |
|
|
else: |
|
|
kwargs[k] = v |
|
|
|
|
|
|
|
|
fullargspec = inspect.getfullargspec(cls.__init__) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
arg_name_list = fullargspec.args |
|
|
|
|
|
|
|
|
if fullargspec.defaults is not None: |
|
|
l = len(fullargspec.defaults) |
|
|
default_args = fullargspec.args[-l:] |
|
|
for k, v in zip(default_args, fullargspec.defaults): |
|
|
if k in kwargs: |
|
|
continue |
|
|
else: |
|
|
kwargs[k] = v |
|
|
|
|
|
|
|
|
if fullargspec.kwonlydefaults is not None: |
|
|
for k, v in fullargspec.kwonlydefaults.items(): |
|
|
if k in kwargs: |
|
|
continue |
|
|
else: |
|
|
kwargs[k] = v |
|
|
|
|
|
|
|
|
|
|
|
kwargs = dict() |
|
|
for arg_name in arg_name_list: |
|
|
if arg_name == 'self': |
|
|
continue |
|
|
try: |
|
|
value = args.pop(0) |
|
|
except IndexError: |
|
|
break |
|
|
kwargs[arg_name] = value |
|
|
|
|
|
if fullargspec.varargs is not None: |
|
|
kwargs[fullargspec.varargs] = tuple(args) |
|
|
|
|
|
return kwargs |
|
|
|
|
|
@classmethod |
|
|
def flush(cls): |
|
|
cls.__instance = list() |
|
|
return |
|
|
|
|
|
|
|
|
def demo1(): |
|
|
class A(ParamsSingleton): |
|
|
pass |
|
|
|
|
|
class B(A): |
|
|
|
|
|
def __init__(self, name, age=27, **kwargs): |
|
|
|
|
|
pass |
|
|
|
|
|
b1 = B('jack') |
|
|
print('-' * 25) |
|
|
|
|
|
|
|
|
b3 = B(name='jack', **{'age': 25, 'high': 165}) |
|
|
|
|
|
|
|
|
print('-' * 25) |
|
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
demo1() |
|
|
|