最近,我在考虑如何用Python实现单例模式。如果 Singleton 类没有子类,下面的代码可以正常工作。
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._instance
Run Code Online (Sandbox Code Playgroud)
但是,Singleton 类可能有子类。
class SingletonSub1(Singleton):
def __new__(cls, *args, **kwargs):
return super(SingletonSub1, cls).__new__(cls, *args, **kwargs)
class SingletonSub2(Singleton):
def __new__(cls, *args, **kwargs):
return super(SingletonSub1, cls).__new__(cls, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
要求是系统中只能有 1 个实例,即 Singleton、SingletonSub1 或 SingletonSub2。我怎样才能实现这个?我知道我绝对可以使用模块级变量来保存 Singleton 对象。但这确实是一个糟糕的代码......
我正在尝试制作一个单调模式:
class Room:
obj = None
def __new__(cls):
if cls.obj is None:
cls.obj = object.__new__(cls)
return cls.obj
def __init__(self, left_wall, right_wall, front_wall, back_wall):
self.left_wall = left_wall
self.right_wall = right_wall
self.front_wall = front_wall
self.back_wall = back_wall
def __str__(self):
return str(self.left_wall) + str(self.right_wall) + str(self.front_wall) + str(self.back_wall)
room_obj = Room(True, False, True, True)
print(room_obj)
room_obj2 = Room(True, False, False, True)
print(room_obj2)
print(room_obj is room_obj2)
Run Code Online (Sandbox Code Playgroud)
运行此代码后,在控制台中得到以下内容:
kalinin@kalinin ~/python/object2 $ python index.py
TrueFalseTrueTrue
TrueFalseFalseTrue
False
Run Code Online (Sandbox Code Playgroud)
它不应该创建两个对象
在异步函数中,每个记录器语句都会获取自己的 request_id。
import logging
log = logging.getLogger('test_logger')
def sync_fun():
log.info("test 1")
log.info("test 2")
log.info("test 3")
@after_response.enable
def async_fun():
log.info("test 1")
log.info("test 2")
log.info("test 3")
output of sync_fun:
[06/Nov/2019 10:42:00.234] [None] [130C6C47F1E24164AAC0440C719630] [INFO] Test 1
[06/Nov/2019 10:42:00.234] [None] [130C6C47F1E24164AAC0440C719630] [INFO] Test 2
[06/Nov/2019 10:42:00.234] [None] [130C6C47F1E24164AAC0440C719630] [INFO] Test 3
Run Code Online (Sandbox Code Playgroud)
130C6C47F1E24164AAC0440C719630 是一个 request_id,对于所有记录器语句都是通用的。
output of async_fun:
[06/Nov/2019 10:42:00.234] [None] [AB352B8F2DF9459ABDD2FBF51EB05F] [INFO] Test 1
[06/Nov/2019 10:42:00.234] [None] [V9E9B6DF5F9C442195EA7C1379FBFA] [INFO] Test 2
[06/Nov/2019 10:42:00.234] [None] [DCA311A92724443C9AD7E951288917] [INFO] Test 3
Run Code Online (Sandbox Code Playgroud)
async_fun 是一个异步函数,所有记录器语句的请求 ID 都不同。
如何为异步函数中的每个记录器语句获取相同的 …
我有一个像这样的单身人士
class Singleton:
class __impl:
def __init__(self):
print "INIT"
__instance = None
def __init__(self):
# Check whether we already have an instance
if Singleton.__instance is None:
Singleton.__instance = Singleton.__impl()
# Store instance reference as the only member in the handle
self.__dict__['_Singleton__instance'] = Singleton.__instance
def __getattr__(self, attr):
""" Delegate access to implementation """
return getattr(self.__instance, attr)
def __setattr__(self, attr, value):
""" Delegate access to implementation """
return setattr(self.__instance, attr, value)
Run Code Online (Sandbox Code Playgroud)
当我做了几个Singleton的实例时,我得到了两个init的调用,我的意思是"INIT"被打印了两次,我觉得它不应该发生
有人知道这有什么问题或有更好的方法来实现这个?
我有一个名为EventManager的类,我在每个模块中调用这个类.我想到在主文件中创建一个EventManager的实例,并在每个模块中使用该实例.我的问题是:
class Singleton:
instance = None
def __new__(cls):
if cls.instance is None:
cls.instance = super().__new__(cls)
return cls.instance
singleton_obj1 = Singleton()
singleton_obj2 = Singleton()
print(singleton_obj1)
print(singleton_obj2)
Run Code Online (Sandbox Code Playgroud)
产量
<__main__.Singleton object at 0x10dbc0f60>
<__main__.Singleton object at 0x10dbc0f60>
Run Code Online (Sandbox Code Playgroud)
有人可以解释这一行究竟发生了什么cls.instance = super().__new__(cls).哪一行代码有助于创建这个类Singleton?
我正在寻找正确的方法来创建在第一次创建中接受参数的单例类。我的研究将我引向3种不同的方式:
元类
class Singleton(type):
instance = None
def __call__(cls, *args, **kwargs):
if cls.instance is None:
cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
return cls.instance
class ASingleton(metaclass=Singleton):
pass
Run Code Online (Sandbox Code Playgroud)
__新__
class Singleton(object):
instance = None
def __new__(cls, *args, **kwargs):
if cls.instance is None:
cls.instance = super().__new__(cls, *args, **kwargs)
return cls.instance
Run Code Online (Sandbox Code Playgroud)
装饰器
def Singleton(myClass):
instances={}
def getInstance(*args, **kwargs):
if myClass not in instances:
instances[myClass] = myClass(*args, **kwargs)
return instances[myClass]
return getInstance
@Singleton
class SingletonTest(object):
pass
Run Code Online (Sandbox Code Playgroud)
所有这些都可以正常工作,但是当涉及到初始化时(例如在普通类中使用__init__),我无法找出实现它的正确方法。我能想到的唯一解决方案是以这种方式使用metaclass方法:
class Singleton(type):
instance = None
def __call__(cls, …Run Code Online (Sandbox Code Playgroud) 我有一个单例的 Python (3.8) 元类,如下所示
我尝试添加如下类型:
from typing import Dict, Any, TypeVar, Type
_T = TypeVar("_T", bound="Singleton")
class Singleton(type):
_instances: Dict[Any, _T] = {}
def __call__(cls: Type[_T], *args: Any, **kwargs: Any) -> _T:
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
Run Code Online (Sandbox Code Playgroud)
在行中:
_instances: Dict[Any, _T] = {}
Run Code Online (Sandbox Code Playgroud)
MyPy 警告:
Mypy: Type variable "utils.singleton._T" is unbound
我已经尝试了不同的迭代,但没有成功;我很难弄清楚如何输入这个字典。
此外,该行:
_instances: Dict[Any, _T] = {}
Run Code Online (Sandbox Code Playgroud)
生产:
Mypy: The erased type of self "Type[golf_ml.utils.singleton.Singleton]" is not a supertype of its class …
可能重复:
在Python中定义单例是否有简单,优雅的方法?
我有以下示例代码,其中我从Singleton派生一个类(希望它是一个):
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = object.__new__(cls, *args, **kwargs)
return cls._instance
class Tracer(Singleton):
def __init__(self):
print "Init"
a = Tracer()
b = Tracer()
Run Code Online (Sandbox Code Playgroud)
当你尝试它时,你会看到再次调用__init__方法Tracer.是不是有单身人士让另一个实例引用原始实例?我不想__init__再次运行该方法,因为它可能会覆盖以前的信息.也许单身人士是错的还是有用的?
我试图为我的项目和 StackOverflow 中的一个有趣的帖子实现单例类
我决定采用提到的元类方法。
现在..我尝试添加一个方法来获取和清除实例(以防用户想要摆脱当前实例并创建一个新实例..):
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]
def getInstance(cls):
print("Class is {}".format(cls.__name__))
if not cls in cls._instances:
raise LookupError("No instance of the class {cls} create yet.".format(cls.__name__))
return cls._instances[cls]
def clearInstance(cls):
cls._instances.pop(cls, None)
class someClass(metaclass=Singleton):
def __init__(self,val):
self.value = val
Run Code Online (Sandbox Code Playgroud)
我能够成功创建对象..
In [9]: sc = someClass(1)
In [10]: sc.value
Out[10]: 1
Run Code Online (Sandbox Code Playgroud)
但是当我这样做时dir(someClass),两种方法都没有显示:
class Singleton(type):
_instances = {} …Run Code Online (Sandbox Code Playgroud)