Python-Borg设计模式,创建类的运行方法
我正在尝试实现这里找到的博格设计模式(在下面重新创建): 我想在这个类的第一次初始化时运行一个特定的方法,但以后不再运行。最初,我尝试使用一些布尔标志,但据我所知,Singleton类被多次初始化,但状态和行为在所有实例中都是通用的。因此,我在init方法中进行的任何初始化都会发生多次,因此每次初始化Singleton方法时都会重置标志 我找到了一个有效的解决方案,但我想知道什么是最适合做这件事的方法,因为我不相信这就是它。我做了以下工作:Python-Borg设计模式,创建类的运行方法,python,variables,design-patterns,Python,Variables,Design Patterns,我正在尝试实现这里找到的博格设计模式(在下面重新创建): 我想在这个类的第一次初始化时运行一个特定的方法,但以后不再运行。最初,我尝试使用一些布尔标志,但据我所知,Singleton类被多次初始化,但状态和行为在所有实例中都是通用的。因此,我在init方法中进行的任何初始化都会发生多次,因此每次初始化Singleton方法时都会重置标志 我找到了一个有效的解决方案,但我想知道什么是最适合做这件事的方法,因为我不相信这就是它。我做了以下工作: class Singleton(Borg): def
class Singleton(Borg):
def __init__(self, arg):
Borg.__init__(self)
if not self.__dict__: #I'm just checking that the namespace is empty, knowing it will be filled with something in the future.
firstInitializationMethod()
非常感谢您的帮助,如果需要更多详细信息,请告诉我。我是新来的。谢谢 我认为您的解决方案并没有那么糟糕,需要注意的是,您必须在下次调用
init
或将多次调用firstInitializationMethod()
之前填充该。由于self.val=arg
,在您的示例中肯定会发生这种情况
然而,如果您的Simpleton在其\uuuuu init\uuuuu
调用中的类实例名称空间内不执行赋值,那么您的解决方案可能会失败
更直接、更健壮的方法是像这样使用class属性:
class Singleton(Borg):
_first_initialization = True
def __init__(self,arg):
Borg.__init__(self)
if Singleton._first_initialization:
firstInitializationMethod()
Singleton._first_initialization = False
您可以通过将firstInitializationMethod()
替换为print并创建一些Simpleton
对象来测试这段代码,以确保只调用一次
这是可行的,并且在每次调用\uuuuuu init\uuuuuu
时,\u first\u初始化
不会被覆盖回True
,因为类名称空间与类实例名称空间是分开的,而Borg只会影响后者(即使Simpleton的所有实例使用相同的\uu dict\uuu
)
后续问题:
我尝试了self而不是Singleton的代码,它仍然有效。他们似乎决心做同样的事。是否有理由使用Singleton
考虑使用这两种方法的代码,SingletonSelfless
是使用Singleton的方法。\u first\u initialization
,tinker()
只是返回self。\u first\u initialization
:
a = Singleton('a')
print(a)
b = Singleton('b')
print(a,b)
c = Singleton('c')
print(a,b,c)
print(Singleton._first_initialization, a.tinker(),b.tinker(),c.tinker())
a = SingletonSelfless('a')
print(a)
b = SingletonSelfless('b')
print(a,b)
c = SingletonSelfless('c')
print(a,b,c)
print(SingletonSelfless._first_initialization, a.tinker(),b.tinker(),c.tinker())
class Singleton(Borg):
_first_initialization = True
def __init__(self,arg):
Borg.__init__(self)
if self._first_initialization:
print('doing some init!!')
self._first_initialization = False
self.val = arg
def tinker(self):
return self._first_initialization
def __str__(self): return self.val
其输出:
doing some init!!
a
b b
c c c
True False False False
doing some init!!
a
b b
c c c
False False False False
从实际的角度来看,这两种实现都像我们希望的那样工作,但与\u first\u初始化
变量值存在明显差异
答案很简单。
即使类名称空间和类实例名称空间是分开的,实例仍然可以访问类名称空间。
但它只是作为回退—类实例名称空间具有绝对优先级—但当它在自己的实例名称空间中找不到名称时,它会尝试使用类1。
那么让我们看看这篇单例中的\uuuu init\uuuu
:
a = Singleton('a')
print(a)
b = Singleton('b')
print(a,b)
c = Singleton('c')
print(a,b,c)
print(Singleton._first_initialization, a.tinker(),b.tinker(),c.tinker())
a = SingletonSelfless('a')
print(a)
b = SingletonSelfless('b')
print(a,b)
c = SingletonSelfless('c')
print(a,b,c)
print(SingletonSelfless._first_initialization, a.tinker(),b.tinker(),c.tinker())
class Singleton(Borg):
_first_initialization = True
def __init__(self,arg):
Borg.__init__(self)
if self._first_initialization:
print('doing some init!!')
self._first_initialization = False
self.val = arg
def tinker(self):
return self._first_initialization
def __str__(self): return self.val
即使实例没有\u first\u初始化
我们的if
正在使用单例进行解析。\u first\u初始化
。
但是,将self.\u first\u initialization
设置为False
将在实例命名空间中创建\u first\u initialization
变量。
同样感谢Borg
我们所有的实例都共享相同的\uuuuu dict\uuuuu
,因此在后续的init调用中,类实例名称空间中将有一个\uu first\u initialization
初始化(首先创建的\uuuu init\uuuuu
调用值False
)
我们的条件语句将按照我们希望的方式进行解析-不执行另一个firstInitializationMethod()
(此处打印以供演示)
但是,驻留在类名称空间中的原始\u first\u初始化
保持不变。这就是为什么我们得到了True-False
在SingletonSelfless
中,我们从不在类实例中创建\u first\u初始化
,因此tinker()调用将回退到类命名空间。这就是为什么有4个FALSE-所有调用都指向同一个对象(SingletonSelfless.\u first\u初始化
bool变量)
而在Singleton
中,我们有两个不同的对象——一个来自类名称空间,另一个在实例之间共享的类实例名称空间。
那么,为什么要使用Singleton.
而不是self.
?首先,我们通过只有一个“first”初始化bool来“节省”极少量的内存!
但真正的原因是很难意外地更改隐藏在类名称空间中的变量。
如果我们使用的是self.\u首先\u初始化
,然后在我们的代码中的某个地方发生了类似的事情,无论出于何种原因(或者来自博格的\u共享\u指令将被清除或更改,从而影响驻留在那里的内容):
a._first\u initialization='Lol'
或在Singleton或其子方法中self._first\u initialization='ROFL'
然后我们在初始化新的单例对象时会遇到一些严重的问题。
使用Singleton.\u first\u initialization
可以,因为用于init的变量只能由显式Singleton修改。\u first\u initialization='bad idea'
我知道这很旧,但我只是想到了以下解决方案:
class Borg(object):
_state = {}
def __new__(cls, hive_name, *p):
self = object.__new__(cls, *p)
if hive_name not in cls._state:
cls._state[hive_name]={}
self.__dict__ = cls._state[hive_name]
self.__init_hive__(*p)
else:
self.__dict__ = cls._state[hive_name]
return self
def __init_hive__(self, *p):
pass
这个实现允许您创建多个共享状态(为了与主题保持一致,我称这些配置单元)并自由分配实例。创建配置单元时,它在配置单元中的第一个实例上调用\uuu init\uu配置单元
方法,并传递实例化参数。比如说
class WeAre(Borg):
def __init__(self, hive_name, arg):
super(WeAre, self).__init__(hive_name, arg)
def __init_hive__(self, arg):
self.hive_arg=arg
# Prints foo
print WeAre("The Collective", "foo").hive_arg
# Prints foo again
print WeAre("The Collective", "bar").hive_arg
# Prints bar
print WeAre("The Hive", "bar").hive_arg
这部分是不相关的,但我尝试了使用self
而不是Singleton
的代码,它仍然有效。他们似乎决心做同样的事。是否有理由使用Singleton
?@不同的哲学环境。我会马上把我的答案更新到sh