8

私はこのようなシングルトンを持っています

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)

Singleton のインスタンスをいくつか作成すると、initへの呼び出しが2 回発生しました。つまり、「INIT」が 2 回出力されました。

誰かがこれの何が悪いのか、またはこれを実装するためのより良い方法を知っていますか??

4

4 に答える 4

17

シングルトンを書くための少し簡単な方法は次のとおりです。

class Singleton(object):
    __instance = None
    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = super(Singleton,cls).__new__(cls)
            cls.__instance.__initialized = False
        return cls.__instance

    def __init__(self):      
        if(self.__initialized): return
        self.__initialized = True
        print ("INIT")

a = Singleton()
b = Singleton()
print (a is b)

もっと良い方法があるかもしれませんが。私はシングルトンが好きではなかったことを認めなければなりません。私はファクトリータイプのアプローチを好みます:

class Foo(object):
    pass

def foo_singleton_factory(_singlton = Foo()):
    return _singleton

a = foo_singleton_factory()
b = foo_singleton_factory()
print (a is b)

これには、必要に応じて Foo の同じインスタンスを取得し続けることができるという利点がありますが、10 年後に真のシングルトンが必要ないと判断した場合、単一のインスタンスに限定されません。

于 2012-09-06T17:32:06.323 に答える
8

PEP 318には、クラスのシングルトン デコレータの例があります。

def singleton(cls):
    instances = {}
    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance

@singleton
class MyClass:
    ...

(私自身は使っていませんが。)

ところで、約...

私はこのようなシングルトンを作りました

また、 ActiveState から直接コピーしたことにも言及する必要があります。

于 2012-09-06T17:32:45.120 に答える
3

私たちは皆あなたの質問を無視しており、代わりに代替のシングルトン実装を提案しているので、私のお気に入りに参加します. これは、Python モジュールを何回インポートしても、一度しかロードされないという事実を利用しています。

また、Python のモットーである "私たちは皆、大人の同意を得ています" にも基づいています。なぜなら、本当にしたいのであれば、複数回インスタンス化することができます...しかし、それを間違って行うには、本当に余分な努力をしなければならないからです。

だからでmysingleton.py

class SingletonClass(object):
    def __init__(self):
        # There's absolutely nothing special about this class
        # Nothing to see here, move along
        pass

# Defying PEP8 by capitalizing name
# This is to point out that this instance is a Singleton
Singleton = SingletonClass()

# Make it a little bit harder to use this module the wrong way
del SingletonClass

次に、次のように使用します。

from mysingleton import Singleton

# Use it!

間違ったことをするために余計な努力をしなければならないと言いました。シングルトン クラスの 2 つのインスタンスを作成して、シングルトンではなくする方法を次に示します。

another_instance = Singleton.__class__()

では、この問題を回避するにはどうすればよいでしょうか。私は医者を引用します:それをしないでください!


注:これは、以下のコメントが作成された後に追加されました

私がそれに取り組んでいる間、複雑なコードの量を最小限に抑える別のシングルトンバリアントを次に示します。メタクラスを使用します:

class SingletonMeta(type):
    # All singleton methods go in the metaclass
    def a_method(cls):
        return cls.attribute

    # Special methods work too!
    def __contains__(cls, item):
        return item in cls.a_list

class Singleton(object):
    __metaclass__ = SingletonMeta
    attribute = "All attributes are class attributes"

    # Just put initialization code directly into the class
    a_list = []
    for i in range(0, 100, 3):
        a_list.append(i)

print Singleton.a_method()
print 3 in Singleton

Python 3 では、代わりに次のようにシングルトン インスタンスを作成します。

class Singleton(metaclass=SingletonMeta):
    attribute = "One... two... five!"

singleton はclassであり、singletonのインスタンスを作成できるため、これはもう少し不安定です。シングルトンはインスタンスがあってもシングルトンのままであるため、理論的にはこれで問題ありませんが、シングルトンではないことを覚えておく必要があります。シングルトン属性をそのインスタンスでクラス属性としてすぐに使用できるようにする必要がある場合もあります。Singleton()Singleton

于 2012-09-06T17:46:59.177 に答える
1

別の方法:

>>> class Singleton(object):
...     def __new__(cls, *args, **kwargs):
...             try:
...                     return cls._instance
...             except AttributeError:
...                     val = cls._instance = object.__new__(cls, *args, **kwargs)
...                     return val
... 
>>> class A(Singleton): pass
... 
>>> a = A()
>>> a2 = A()
>>> a2 is a
True
>>> class B(Singleton): pass
... 
>>> b = B()
>>> b2 = B()
>>> b2 is b
True
>>> b is a
False
>>> class D(Singleton):
...     def __init__(self, v): self.v = v
... 
>>> d = D(1)
>>> d.v
1

複数の呼び出しが心配な場合は__init__、デコレータを使用するか、メタクラスを使用するかを選択してください。

返された値がそのクラスのインスタンスである場合、 python は常に返されたオブジェクトのメソッドを呼び出すため、メソッドをオーバーライドすると__new__複数の呼び出しが可能になります。__init____init____new__

とにかく、デコレータを使用するのが最善だと思います。おそらくそれがより簡単な解決策だからです。

Python でシングルトンを作成する方法をもっと知りたい場合は、この質問を読んでください。

ところで、すべてのインスタンスを同じ状態 (ID ではなく) にしたい場合は、Borgパターンに関心があるかもしれません。どちらを選択すればよいかわからない場合は、この回答を参照してください。

于 2012-09-06T17:38:41.170 に答える