[英]How to make a singleton object with an arbitrary number of keyword arguments in Python?
我正在使用任意数量的关键字参数制作单例。 在调试类时,执行后显示的异常与调试跟踪的发展方式不匹配。
我尝试使用/和* ,因为在官方文档中提到了一些特殊情况,但是没有用。
class A:
class B:
def __init__(self, *, arg1, arg2, arg3, arg4='default'):
self.arg1 = arg1
self.arg2 = arg2
self.arg3 = arg3
self.arg4 = arg4
_singleton_instance = None
def __init__(self, **args):
if not A._singleton_instance:
_singleton_instance = A.B(**args)
def __getattribute__(self, name):
getattr(self._instance, name)
A(arg1=1, arg2=2, arg3=3)
A.arg1
执行后的异常说:
AttributeError: type object 'A' has no attribute 'arg1'
。
仅在调试时出现的异常说:
RecursionError('maximum recursion depth exceeded',)
在 Python 3 中,您可以使用类似这样的元类来缓存具有各种不同参数集的A
对象。
但是,如果传入的任何参数不可散列,这将失败。
import inspect
class Singleton(type):
def __call__(cls, *args, **kwargs):
# Compute a cache key based on the arguments passed in and applying
# any defaults from the original __init__ signature
ar = inspect.signature(cls.__init__).bind_partial(*args, **kwargs)
ar.apply_defaults()
key = frozenset(ar.arguments.items())
# Initialize the cache if it doesn't exist yet
if not hasattr(cls, "_singleton_cache"):
cls._singleton_cache = {}
# If the key is in the cache, return it
cache = cls._singleton_cache
if key in cache:
return cache[key]
# Otherwise initialize a new object, save it and return it
cache[key] = obj = super().__call__(*args, **kwargs)
return obj
class A(metaclass=Singleton):
def __init__(self, *, arg1, arg2, arg3, arg4="default"):
self.arg1 = arg1
self.arg2 = arg2
self.arg3 = arg3
self.arg4 = arg4
a = A(arg1=1, arg2=2, arg3=3)
b = A(arg1=1, arg2=2, arg3=3)
print(a is b)
编辑:如果你真的,真的想要一个忽略任何新参数集的单例元类,那么你去......
class VerySingleton(type):
def __call__(cls, *args, **kwargs):
if not hasattr(cls, "_singleton_cache"):
# Initialize the new object
cls._singleton_cache = super().__call__(*args, **kwargs)
return cls._singleton_cache
class A(metaclass=VerySingleton):
def __init__(self, *, arg1, arg2, arg3, arg4="default"):
self.arg1 = arg1
self.arg2 = arg2
self.arg3 = arg3
self.arg4 = arg4
a = A(arg1=1, arg2=2, arg3=3)
b = A(arg1=1, arg2=2, arg3=0)
print(a is b)
print(a.arg3)
print(b.arg3)
这打印出来
True
3
3
– 无论b
是否使用arg3=0
构造,它都会被丢弃并使用旧实例,如果你问我,这完全违反直觉。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.