首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >清除MetaClass单例

清除MetaClass单例
EN

Stack Overflow用户
提问于 2018-04-27 15:05:21
回答 2查看 2.6K关注 0票数 2

正如在MetaClass中讨论的那样,我使用Method 3 of this answer创建了一个Singleton

代码语言:javascript
复制
 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()方法的正确咒语:

代码语言:javascript
复制
     def clear(self):
       try:
          del(Singleton._instances[type(self)]
       except KeyError:
          pass   #Sometimes we clear before creating

对我做错了什么有什么想法吗?我的独身人不会被批准的。

代码语言:javascript
复制
sing=MySing()
sing.clear()

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-04-27 15:31:40

让我们来看一遍(更正的) Singleton定义和使用它定义的类。我将使用cls替换为Singleton,其中的查找无论如何都是通过的。

代码语言:javascript
复制
 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__并没有做太多事情)。

票数 10
EN

Stack Overflow用户

发布于 2018-04-27 15:31:13

我第一眼就看到了这个元类的三个有用的测试用例。

  • 测试单个类创建是否正常工作。
  • 测试在初始类之后是否没有创建新类。
  • 测试多个类是否可以结合使用这个元类。

所有这些测试都可以在没有“重置”按钮的情况下实现。在那之后,你将覆盖你的大部分基地。(我可能忘了一个)。

只需创建几个使用此元类的不同TestClasses,并检查它们的Id和类型。

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50065276

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档