gpt4 book ai didi

python - 清除元类单例

转载 作者:行者123 更新时间:2023-12-05 09:16:35 25 4
gpt4 key购买 nike

我已经使用 MetaClass 创建了一个 Singleton,如 Method 3 of this answer 中所述

 class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]


class MySing(metaclass=Singleton): ...

我希望能够在 unittest.TestCasesetUp() 方法中清除 Singleton,以便每个测试都以一个干净的 Singleton 开始。

我想我真的不明白这个元类在做什么,因为我无法获得 clear() 方法的正确咒语:

     def clear(self):
try:
del(Singleton._instances[type(self)]
except KeyError:
pass #Sometimes we clear before creating

对我在这里做错了什么有什么想法吗?我的单例没有被清除。

sing=MySing()
sing.clear()

上面的 type 调用返回 Singleton 而不是 MySing

最佳答案

让我们来看看 Singleton 的(更正的)定义和使用它定义的类。我正在用 Singleton 替换 cls 的使用,无论如何都会通过查找。

 class Singleton(type):
_instances = {}

# Each of the following functions use cls instead of self
# to emphasize that although they are instance methods of
# Singleton, they are also *class* methods of a class defined
# with Singleton
def __call__(cls, *args, **kwargs):
if cls not in Singleton._instances:
Singleton._instances[cls] = super().__call__(*args, **kwargs)
return Singleton._instances[cls]

def clear(cls):
try:
del Singleton._instances[cls]
except KeyError:
pass

class MySing(metaclass=Singleton):
pass

s1 = MySing() # First call: actually creates a new instance
s2 = MySing() # Second call: returns the cached instance
assert s1 is s2 # Yup, they are the same
MySing.clear() # Throw away the cached instance
s3 = MySing() # Third call: no cached instance, so create one
assert s1 is not s3 # Yup, s3 is a distinct new instance

首先,_instances 是元类的类属性,用于将类映射到该类的唯一实例。

__call__ 是元类的实例方法;它的目的是使元类(即类)的实例可调用。 cls 这里是定义的类,不是元类。因此,每次调用 MyClass() 时,都会转换为 Singleton.__call__(MyClass)

clear 也是元类的实例方法,这意味着它也将元类的实例(即类)作为参数(不是用元类。)这意味着 MyClass.clear()Singleton.clear(MyClass) 相同。 (这也意味着您可以,但为了清楚起见,可能不应该编写 s1.clear()。)

元类实例方法与“常规”类类方法的标识也解释了为什么需要在元类中使用 __call__ 而在常规类中使用 __new__ class: __new__ 是一种特殊的类方法,无需对其进行修饰。元类为它的实例定义实例方法有点棘手,所以我们只使用__call__(因为type.__call__ 除了调用正确的 __new__ 方法外,没有做太多事情。

关于python - 清除元类单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50065276/

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