- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这个问题不是讨论singleton design pattern是可取的,是一种反模式,或用于任何宗教 war ,但要讨论如何以最 pythonic 的方式在 Python 中最好地实现这种模式。在这种情况下,我定义“最pythonic”意味着它遵循“最小惊讶原则”。
我有多个类将成为单例(我的用例是记录器,但这并不重要)。当我可以简单地继承或装饰时,我不希望用添加的口香糖来混淆几个类。
最佳方法:
方法一:装饰器
def singleton(class_):
instances = {}
def getinstance(*args, **kwargs):
if class_ not in instances:
instances[class_] = class_(*args, **kwargs)
return instances[class_]
return getinstance
@singleton
class MyClass(BaseClass):
pass
优点
x = MyClass();
y = MyClass();
t = type(n)();
然后
x == y
但是
x != t && y != t
class Singleton(object):
_instance = None
def __new__(class_, *args, **kwargs):
if not isinstance(class_._instance, class_):
class_._instance = object.__new__(class_, *args, **kwargs)
return class_._instance
class MyClass(Singleton, BaseClass):
pass
优点
__new__
在从第二个基类继承期间可以覆盖吗?一个人必须想得比必要的多。 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]
#Python2
class MyClass(BaseClass):
__metaclass__ = Singleton
#Python3
class MyClass(BaseClass, metaclass=Singleton):
pass
优点
__metaclass__
出于其正当目的(并让我意识到这一点)def singleton(class_):
class class_w(class_):
_instance = None
def __new__(class_, *args, **kwargs):
if class_w._instance is None:
class_w._instance = super(class_w,
class_).__new__(class_,
*args,
**kwargs)
class_w._instance._sealed = False
return class_w._instance
def __init__(self, *args, **kwargs):
if self._sealed:
return
super(class_w, self).__init__(*args, **kwargs)
self._sealed = True
class_w.__name__ = class_.__name__
return class_w
@singleton
class MyClass(BaseClass):
pass
优点
_sealed
的意义何在?属性 super()
在基类上调用同名方法因为它们会递归。这意味着您无法自定义 __new__
并且不能子类化需要您调用的类 __init__
. singleton.py
优点
最佳答案
使用元类
我会推荐 方法#2 ,但最好使用 元类比基类。这是一个示例实现:
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 Logger(object):
__metaclass__ = Singleton
或者在 Python3 中
class Logger(metaclass=Singleton):
pass
如果你想运行
__init__
每次调用类时,添加
else:
cls._instances[cls].__init__(*args, **kwargs)
到
if
声明于
Singleton.__call__
.
type(obj)
在 Python 中找到对象的元类.普通的新式类的类型是
type
.
Logger
在上面的代码中,类型为
class 'your_module.Singleton'
,就像
Logger
的(唯一)实例一样类型为
class 'your_module.Logger'
.当您使用
Logger()
调用记录器时,Python首先询问
Logger
的元类,
Singleton
,做什么,允许实例创建被抢占。这个过程与 Python 通过调用
__getattr__
来询问类要做什么相同。当您通过执行
myclass.attribute
来引用它的属性之一时.
struct
s 在 Python 中使用元类。线程
What are some (concrete) use-cases for metaclasses?还提供了一些示例,它们通常似乎与声明式编程有关,尤其是在 ORM 中使用的。
__new__
方法,它将是
每次都执行 您拨打
SubClassOfSingleton()
-- 因为它负责调用返回存储实例的方法。使用元类,它将
只被调用一次 ,当唯一的实例被创建时。您要
自定义调用类的含义 ,这是由它的类型决定的。
__call__
这不太可能成为问题。实例字典是
不在实例的命名空间中 所以它不会意外地覆盖它。
type
的子类,可以使用 1 在运行时动态创建中间基类,并将其作为元类,然后将其用作公共(public)基类
Singleton
基类。解释比做更难,如下图所示:
# works in Python 2 & 3
class _Singleton(type):
""" A metaclass that creates a Singleton base class when called. """
_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 Singleton(_Singleton('SingletonMeta', (object,), {})): pass
class Logger(Singleton):
pass
这种方法具有讽刺意味的是,它使用子类化来实现元类。一个可能的优点是,与纯元类不同,
isinstance(inst, Singleton)
将返回
True
.
_instances
需要
在类(class)中引用 ,您需要使用
super()
或者你是
递归 , 和
__new__
实际上是一个静态方法,你必须
将类(class)传递给 ,不是类方法,作为实际类
尚未创建 然而当它被调用时。所有这些事情对于元类实现也是如此。
class Singleton(object):
_instances = {}
def __new__(class_, *args, **kwargs):
if class_ not in class_._instances:
class_._instances[class_] = super(Singleton, class_).__new__(class_, *args, **kwargs)
return class_._instances[class_]
class MyClass(Singleton):
pass
c = MyClass()
装饰器返回一个类
__class__
中,这不是很奇怪吗?属性?这也意味着你不能定义
任何在其基类上调用同名方法的方法 与
super()
因为它们会递归。这意味着您的类(class)无法自定义
__new__
,并且不能从任何需要
__init__
的类派生呼唤他们。
Now, there is one kind of Singleton which is OK. That is a singleton where all of the reachable objects are immutable. If all objects are immutable than Singleton has no global state, as everything is constant. But it is so easy to turn this kind of singleton into mutable one, it is very slippery slope. Therefore, I am against these Singletons too, not because they are bad, but because it is very easy for them to go bad. (As a side note Java enumeration are just these kind of singletons. As long as you don't put state into your enumeration you are OK, so please don't.)
The other kind of Singletons, which are semi-acceptable are those which don't effect the execution of your code, They have no "side effects". Logging is perfect example. It is loaded with Singletons and global state. It is acceptable (as in it will not hurt you) because your application does not behave any different whether or not a given logger is enabled. The information here flows one way: From your application into the logger. Even thought loggers are global state since no information flows from loggers into your application, loggers are acceptable. You should still inject your logger if you want your test to assert that something is getting logged, but in general Loggers are not harmful despite being full of state.
关于python - 在 Python 中创建单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6760685/
我正在处理一组标记为 160 个组的 173k 点。我想通过合并最接近的(到 9 或 10 个组)来减少组/集群的数量。我搜索过 sklearn 或类似的库,但没有成功。 我猜它只是通过 knn 聚类
我有一个扁平数字列表,这些数字逻辑上以 3 为一组,其中每个三元组是 (number, __ignored, flag[0 or 1]),例如: [7,56,1, 8,0,0, 2,0,0, 6,1,
我正在使用 pipenv 来管理我的包。我想编写一个 python 脚本来调用另一个使用不同虚拟环境(VE)的 python 脚本。 如何运行使用 VE1 的 python 脚本 1 并调用另一个 p
假设我有一个文件 script.py 位于 path = "foo/bar/script.py"。我正在寻找一种在 Python 中通过函数 execute_script() 从我的主要 Python
这听起来像是谜语或笑话,但实际上我还没有找到这个问题的答案。 问题到底是什么? 我想运行 2 个脚本。在第一个脚本中,我调用另一个脚本,但我希望它们继续并行,而不是在两个单独的线程中。主要是我不希望第
我有一个带有 python 2.5.5 的软件。我想发送一个命令,该命令将在 python 2.7.5 中启动一个脚本,然后继续执行该脚本。 我试过用 #!python2.7.5 和http://re
我在 python 命令行(使用 python 2.7)中,并尝试运行 Python 脚本。我的操作系统是 Windows 7。我已将我的目录设置为包含我所有脚本的文件夹,使用: os.chdir("
剧透:部分解决(见最后)。 以下是使用 Python 嵌入的代码示例: #include int main(int argc, char** argv) { Py_SetPythonHome
假设我有以下列表,对应于及时的股票价格: prices = [1, 3, 7, 10, 9, 8, 5, 3, 6, 8, 12, 9, 6, 10, 13, 8, 4, 11] 我想确定以下总体上最
所以我试图在选择某个单选按钮时更改此框架的背景。 我的框架位于一个类中,并且单选按钮的功能位于该类之外。 (这样我就可以在所有其他框架上调用它们。) 问题是每当我选择单选按钮时都会出现以下错误: co
我正在尝试将字符串与 python 中的正则表达式进行比较,如下所示, #!/usr/bin/env python3 import re str1 = "Expecting property name
考虑以下原型(prototype) Boost.Python 模块,该模块从单独的 C++ 头文件中引入类“D”。 /* file: a/b.cpp */ BOOST_PYTHON_MODULE(c)
如何编写一个程序来“识别函数调用的行号?” python 检查模块提供了定位行号的选项,但是, def di(): return inspect.currentframe().f_back.f_l
我已经使用 macports 安装了 Python 2.7,并且由于我的 $PATH 变量,这就是我输入 $ python 时得到的变量。然而,virtualenv 默认使用 Python 2.6,除
我只想问如何加快 python 上的 re.search 速度。 我有一个很长的字符串行,长度为 176861(即带有一些符号的字母数字字符),我使用此函数测试了该行以进行研究: def getExe
list1= [u'%app%%General%%Council%', u'%people%', u'%people%%Regional%%Council%%Mandate%', u'%ppp%%Ge
这个问题在这里已经有了答案: Is it Pythonic to use list comprehensions for just side effects? (7 个答案) 关闭 4 个月前。 告
我想用 Python 将两个列表组合成一个列表,方法如下: a = [1,1,1,2,2,2,3,3,3,3] b= ["Sun", "is", "bright", "June","and" ,"Ju
我正在运行带有最新 Boost 发行版 (1.55.0) 的 Mac OS X 10.8.4 (Darwin 12.4.0)。我正在按照说明 here构建包含在我的发行版中的教程 Boost-Pyth
学习 Python,我正在尝试制作一个没有任何第 3 方库的网络抓取工具,这样过程对我来说并没有简化,而且我知道我在做什么。我浏览了一些在线资源,但所有这些都让我对某些事情感到困惑。 html 看起来
我是一名优秀的程序员,十分优秀!