Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-Borg设计模式,创建类的运行方法_Python_Variables_Design Patterns - Fatal编程技术网

Python-Borg设计模式,创建类的运行方法

Python-Borg设计模式,创建类的运行方法,python,variables,design-patterns,Python,Variables,Design Patterns,我正在尝试实现这里找到的博格设计模式(在下面重新创建): 我想在这个类的第一次初始化时运行一个特定的方法,但以后不再运行。最初,我尝试使用一些布尔标志,但据我所知,Singleton类被多次初始化,但状态和行为在所有实例中都是通用的。因此,我在init方法中进行的任何初始化都会发生多次,因此每次初始化Singleton方法时都会重置标志 我找到了一个有效的解决方案,但我想知道什么是最适合做这件事的方法,因为我不相信这就是它。我做了以下工作: class Singleton(Borg): def

我正在尝试实现这里找到的博格设计模式(在下面重新创建):

我想在这个类的第一次初始化时运行一个特定的方法,但以后不再运行。最初,我尝试使用一些布尔标志,但据我所知,Singleton类被多次初始化,但状态和行为在所有实例中都是通用的。因此,我在init方法中进行的任何初始化都会发生多次,因此每次初始化Singleton方法时都会重置标志

我找到了一个有效的解决方案,但我想知道什么是最适合做这件事的方法,因为我不相信这就是它。我做了以下工作:

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