gpt4 book ai didi

python - 如何在Python中创建具有任意数量关键字参数的单例对象?

转载 作者:行者123 更新时间:2023-12-01 07:32:07 24 4
gpt4 key购买 nike

我正在使用任意数量的关键字参数创建一个单例。在调试类时,执行后显示的异常与调试跟踪的发展方式不匹配。

我使用的实现与我在 web 中发现的非常相似也在这个 question .

我尝试使用 /*,因为在 official documentation 中有一些特殊情况的引用,但没有用。

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:类型对象“A”没有属性“arg1”

仅在调试时出现的异常表示:

RecursionError('超出最大递归深度',)

最佳答案

在 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 构造,它都会被丢弃并使用旧实例,如果你问我,这完全违反直觉.

关于python - 如何在Python中创建具有任意数量关键字参数的单例对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57164740/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com