正如在MetaClass中讨论的那样,我使用Method 3 of this answer创建了一个Singleton
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): ...我希望能够清除setUp()方法中的unittest.TestCase中的Singleton,这样每个测试都从一个干净的Singleton开始。
我想我不太明白这个metaClass在做什么,因为我无法得到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。
发布于 2018-04-27 15:31:40
让我们来看一遍(更正的) Singleton定义和使用它定义的类。我将使用cls替换为Singleton,其中的查找无论如何都是通过的。
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__:__new__作为类方法是特殊的,而不必修饰它。对于一个元类来说,为其实例定义一个实例方法有点棘手,所以我们只使用__call__ (因为除了调用正确的__new__方法之外,type.__call__并没有做太多事情)。
发布于 2018-04-27 15:31:13
我第一眼就看到了这个元类的三个有用的测试用例。
所有这些测试都可以在没有“重置”按钮的情况下实现。在那之后,你将覆盖你的大部分基地。(我可能忘了一个)。
只需创建几个使用此元类的不同TestClasses,并检查它们的Id和类型。
https://stackoverflow.com/questions/50065276
复制相似问题