清除元类单例
Clearing a MetaClass Singleton
我已经使用 Method 3 of this answer
中讨论的 MetaClass 创建了一个单例
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.TestCase
的 setUp()
方法中清除 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
调用 returns Singleton
不是 MySing
.
乍一看,我看到了这个元class三个有用的测试用例。
- 测试单个 class 创建是否正常。
- 测试在第一个class之后是否没有创建新的
。
- 测试多个 class 是否可以结合使用此元class。
所有这些测试都可以在没有 "reset" 按钮的情况下实现 。之后,您将涵盖大部分基础知识。 (我可能忘记了一个)。
只需创建几个使用此元的不同 TestClassesclass 并检查它们的 ID 和类型。
让我们来看看 Singleton
的(更正)定义和使用它定义的 class。我正在用 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
是 metaclass 的一个 class 属性,用于将 class 映射到 class 的唯一实例。
__call__
是metaclass的一个实例方法;它的目的是使 metaclass(即 classes)的实例可调用。 cls
这里是定义的 class, 不是 元 class。所以每次调用 MyClass()
时,都会转换为 Singleton.__call__(MyClass)
.
clear
也是 metaclass 的实例方法,这意味着它还采用 meta class 的实例(即再次 class)作为一个参数(不是用 metaclass 定义的 class 的实例)这意味着 MyClass.clear()
与 Singleton.clear(MyClass)
相同。 (这也意味着你可以,但为了清楚起见,可能不应该写成 s1.clear()
。)
metaclass实例方法与“常规”classclass方法的标识也解释了为什么需要在metaclass中使用__call__
] 在常规 class 中使用 __new__
的地方: __new__
是特殊情况下的 class 方法,无需这样修饰它。 metaclass 为 its 实例定义 instance 方法有点棘手,所以我们只使用 __call__
(因为 type.__call__
除了调用正确的 __new__
方法之外没有做太多事情(如果有的话))。
我已经使用 Method 3 of this answer
中讨论的 MetaClass 创建了一个单例 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.TestCase
的 setUp()
方法中清除 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
调用 returns Singleton
不是 MySing
.
乍一看,我看到了这个元class三个有用的测试用例。
- 测试单个 class 创建是否正常。
- 测试在第一个class之后是否没有创建新的 。
- 测试多个 class 是否可以结合使用此元class。
所有这些测试都可以在没有 "reset" 按钮的情况下实现 。之后,您将涵盖大部分基础知识。 (我可能忘记了一个)。
只需创建几个使用此元的不同 TestClassesclass 并检查它们的 ID 和类型。
让我们来看看 Singleton
的(更正)定义和使用它定义的 class。我正在用 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
是 metaclass 的一个 class 属性,用于将 class 映射到 class 的唯一实例。
__call__
是metaclass的一个实例方法;它的目的是使 metaclass(即 classes)的实例可调用。 cls
这里是定义的 class, 不是 元 class。所以每次调用 MyClass()
时,都会转换为 Singleton.__call__(MyClass)
.
clear
也是 metaclass 的实例方法,这意味着它还采用 meta class 的实例(即再次 class)作为一个参数(不是用 metaclass 定义的 class 的实例)这意味着 MyClass.clear()
与 Singleton.clear(MyClass)
相同。 (这也意味着你可以,但为了清楚起见,可能不应该写成 s1.clear()
。)
metaclass实例方法与“常规”classclass方法的标识也解释了为什么需要在metaclass中使用__call__
] 在常规 class 中使用 __new__
的地方: __new__
是特殊情况下的 class 方法,无需这样修饰它。 metaclass 为 its 实例定义 instance 方法有点棘手,所以我们只使用 __call__
(因为 type.__call__
除了调用正确的 __new__
方法之外没有做太多事情(如果有的话))。