|
|
1
983
使用元类我建议 方法#2 ,但你最好使用 元类 而不是基类。以下是一个示例实现:
或者在Python中3
如果你想跑步
到
关于元类的几句话。元类是
阶级中的阶级
;也就是说,类是
其元类的实例
。您可以在Python中找到对象的元类
元类本质上决定
类的定义是什么意思
以及如何实现这一定义。请参见示例
http://code.activestate.com/recipes/498149/
,本质上再现了C风格
在这种情况下,如果您使用
方法#2
,并且子类定义
一般来说 有道理 使用元类来实现单例。单身汉之所以特别,是因为 仅创建一次 ,元类是您自定义 创建一个类 .使用元类可以 更多的控制 以防您需要以其他方式自定义singleton类定义。
你的单身汉
不需要多重继承
(因为元类不是基类),但是
创建的类的子类
如果使用多重继承,则需要确保singleton类是
第一个/最左边
一个具有重新定义的元类
您还会听到singleton模式违反了“单一责任原则”——每个类都应该这样做 只有一件事 。这样,如果你需要更改另一件代码,你就不必担心会弄乱代码的一件事,因为它们是分离和封装的。元类实现 通过此测试 元类负责 强制执行模式 并且创建的类和子类不需要 意识到他们是单身 。 方法#1 测试失败,正如您所指出的“MyClass本身是一个函数,而不是一个类,所以您不能从中调用类方法。” Python 2和3兼容版本
编写既适用于Python 2又适用于Python 3的东西需要使用稍微复杂一点的方案。由于元类通常是类型的子类
这种方法的一个讽刺之处在于,它使用子类来实现元类。一个可能的优点是与纯元类不同,
更正
关于另一个主题,您可能已经注意到了这一点,但您最初文章中的基类实现是错误的。
装饰师返回课堂我本来是在写评论,但太长了,所以我会在这里添加这个。 方法#4 它比其他decorator版本更好,但它的代码比单例所需的要多,而且它的作用还不太清楚。
主要的问题源于这个类是它自己的基类。首先,让一个类成为一个几乎相同的类的子类,并且只存在于它的
何时使用singleton模式您的用例是 一个更好的例子 想要使用singleton。你在一条评论中说:“对我来说,登录似乎一直是单身汉的自然选择。” 绝对正确 。 当人们说单身汉不好时,最常见的原因是他们 隐式共享状态 。而使用全局变量和顶级模块导入 明确的 共享状态,传递的其他对象通常被实例化。这是一个很好的观点, 除了两个例外 。 第一个,也是在不同地方提到的一个,是当单身汉 常数 .全局常数的使用,特别是枚举,被广泛接受,并被认为是合理的,因为无论怎样, 任何用户都不能为其他用户搞砸 。对于常量singleton也是如此。 第二个例外是相反的——当singleton 只有一个数据接收器 ,而不是数据源(直接或间接)。这就是为什么伐木工人觉得单身是一种“自然”的用途。由于不同的用户 不更改记录器 在其他用户关心的方面 不是真正共享的状态 。这否定了反对singleton模式的主要论点,并使它们成为一个合理的选择,因为它们 易用性 任务。 这是引用自 http://googletesting.blogspot.com/2008/08/root-cause-of-singletons.html :
|
|
|
2
135
模块只导入一次,其他的都想得太多了。不要使用singleton,尽量不要使用globals。 |
|
|
3
86
使用模块。它只导入一次。在其中定义一些全局变量-它们将是singleton的“属性”。添加一些函数-单例的“方法”。 |
|
|
4
61
您可能永远不需要Python中的singleton。只要在一个模块中定义所有的数据和函数,就有了一个事实上的单例:
要使用:
如果你真的必须有一个singleton类,那么我会选择:
要使用:
哪里
|
|
|
5
13
给你一句话:
以下是使用方法:
您的对象急切地被实例化。这可能是你想要的,也可能不是你想要的。 |
|
|
6
12
检查堆栈溢出问题 Is there a simple, elegant way to define singletons in Python? 有几种解决方案。 我强烈建议观看Alex Martelli关于python中设计模式的演讲: part 1 和 part 2 特别地,在第1部分中,他谈到了单态/共享状态对象。 |
|
|
7
9
|
|
|
8
8
使用函数属性也非常简单
|
|
|
9
6
这是我自己实现的singleton。你所要做的就是布置班级;要获得singleton,您必须使用
代码如下:
|
|
|
10
5
我更喜欢这个解决方案,我觉得它非常清晰明了。 例如,如果其他线程已经创建了它,它将使用双重检查。 需要考虑的另一件事是确保反序列化不会创建任何其他实例。 https://gist.github.com/werediver/4396488
|
|
|
11
4
非常简单而且有效! |
|
|
12
4
使用类变量(无装饰器)
通过覆盖
|
|
13
3
方法3看起来非常简洁,但如果您希望程序同时在这两种情况下运行 Python 2 和 Python 3 ,它不起作用。甚至用Python版本的测试来保护单独的变体也失败了,因为Python3版本在Python2中给出了语法错误。 感谢Mike Watkins: http://mikewatkins.ca/2008/11/29/python-2-and-3-metaclasses/ 。如果你想让程序同时在Python2和Python3中运行,你需要做一些事情,比如:
我认为赋值中的“object”需要替换为“BaseClass”,但我还没有尝试过(我已经尝试过如图所示的代码)。 |
|
|
14
3
我要把我的扔到拳击场上。这是一个简单的装饰师。
我认为它比其他一些解决方案有好处:
我确实遇到了一个缺点:真实类的类方法和静态方法不能通过隐藏它的工厂类透明地调用。我很少使用这种方法,从来没有遇到过这种需要,但通过在工厂上使用一个自定义元类可以很容易地纠正它
实际上,我发现一个更有用的相关模式(并不是说经常需要这些东西)是一个“唯一”模式,在该模式中 相同的论点 导致返回相同的实例。也就是说,“每个自变量都有一个单例”。以上内容很好地适应了这一点,并变得更加简洁:
话虽如此,我确实同意一般的建议,如果你认为你需要这些东西,你真的应该停下来问问自己,你是否真的需要。99%的时候,YAGNI。 |
|
|
15
3
我将推荐一个使用元类的优雅解决方案
输出:
从输出中可以看到,只有一个对象被实例化 |
|
|
16
2
好吧,除了同意Python关于模块级全局性的一般建议之外,这个怎么样:
输出为:
|
|
|
17
2
这个怎么样:
将它用作应该是singleton的类的装饰器。像这样:
这与
|
|
|
18
2
这个答案可能不是你想要的。我想要一个singleton,因为只有那个对象才有它的身份,以便与之进行比较
Sentinel Value
.答案很简单,把任何物体
|
|
|
19
2
也许我误解了singleton模式,但我的解决方案是简单实用的(pythonic?)。这段代码实现了两个目标
这就是代码。
输出
|
|
|
20
2
这将是串行化的问题。如果您尝试从文件(pickle)反序列化对象,它将不会使用
|
|
|
21
2
比起从元类派生,我更喜欢decorator语法。我的2美分:
这比提供的其他装饰器有一些好处:
缺点:
如果您需要一个基于构造函数参数的不同实例,则需要改进此解决方案(由 siddhesh-suhas-sathe 提供了这一点)。 最后,正如其他人建议的那样,考虑在python中使用一个模块。模块 是 对象。您甚至可以将它们传递到变量中,并将它们注入到其他类中。 |
|
|
22
2
我只是偶然做了一个简单的,想和大家分享一下。。。
|
|
|
23
2
这与fab的答案略有相似,但并不完全相同。 这个 singleton pattern 不要求我们能够多次调用构造函数。作为一个单例应该只创建一次,难道不应该被看作只创建了一次吗?可以说,“欺骗”构造函数会损害易读性。 所以我的建议是:
这并不排除使用构造函数或字段
…如果你确信
但是
鼓励
用户使用
要完成此操作,您还可以覆盖
进一步改进我感谢那些在评论和编辑方面提供帮助的人,欢迎更多的评论和编辑。虽然我使用Jython,但这应该更通用,并且是线程安全的。
注意事项:
|
|
|
24
1
我不记得在哪里找到了这个解决方案,但从我的非Python专家的角度来看,我发现它是最“优雅”的:
我为什么喜欢这个?没有装饰器,没有元类,没有多重继承。。。如果你决定不想再让它成为单身汉,只需删除
|
|
|
25
1
代码基于 Tolli's answer 。
说明:
|
|
|
26
1
如果您不需要Singleton实例的延迟初始化,那么以下操作应该是简单且线程安全的:
这边
|
|
|
27
1
经过一段时间的努力,我最终想出了以下方法,这样配置对象在从单独的模块调用时只加载一次。元类允许将全局类实例存储在内置dict中,这似乎是目前存储正确程序全局的最简洁的方式。
|
|
|
28
1
您可以使用
|
|
|
29
1
一句话(我并不自豪,但它确实起到了作用):
|
|
|
30
1
方法:一次性使用后覆盖__new__
优点
Cons
|