554 Stimmen

Gibt es eine einfache, elegante Möglichkeit, Singletons zu definieren?

Es scheint viele Möglichkeiten der Definition zu geben Einzelnes in Python. Gibt es eine einheitliche Meinung auf Stack Overflow?

3voto

Mychot sad Punkte 370

OK, Singleton kann gut oder böse sein, ich weiß. Dies ist meine Implementierung, und ich erweitere einfach einen klassischen Ansatz, um einen Cache im Inneren einzuführen und viele Instanzen eines anderen Typs oder viele Instanzen desselben Typs, aber mit unterschiedlichen Argumenten zu erzeugen.

Ich habe es Singleton_group genannt, weil es ähnliche Instanzen zusammenfasst und verhindert, dass ein Objekt der gleichen Klasse mit den gleichen Argumenten erstellt werden kann:

# Peppelinux's cached singleton
class Singleton_group(object):
    __instances_args_dict = {}
    def __new__(cls, *args, **kwargs):
        if not cls.__instances_args_dict.get((cls.__name__, args, str(kwargs))):
            cls.__instances_args_dict[(cls.__name__, args, str(kwargs))] = super(Singleton_group, cls).__new__(cls, *args, **kwargs)
        return cls.__instances_args_dict.get((cls.__name__, args, str(kwargs)))

# It's a dummy real world use example:
class test(Singleton_group):
    def __init__(self, salute):
        self.salute = salute

a = test('bye')
b = test('hi')
c = test('bye')
d = test('hi')
e = test('goodbye')
f = test('goodbye')

id(a)
3070148780L

id(b)
3070148908L

id(c)
3070148780L

b == d
True

b._Singleton_group__instances_args_dict

{('test', ('bye',), '{}'): <__main__.test object at 0xb6fec0ac>,
 ('test', ('goodbye',), '{}'): <__main__.test object at 0xb6fec32c>,
 ('test', ('hi',), '{}'): <__main__.test object at 0xb6fec12c>}

Jedes Objekt trägt den Singleton-Cache... Dies könnte böse sein, aber es funktioniert gut für einige :)

3voto

class Singeltone(type):
    instances = dict()

    def __call__(cls, *args, **kwargs):
        if cls.__name__ not in Singeltone.instances:            
            Singeltone.instances[cls.__name__] = type.__call__(cls, *args, **kwargs)
        return Singeltone.instances[cls.__name__]

class Test(object):
    __metaclass__ = Singeltone

inst0 = Test()
inst1 = Test()
print(id(inst1) == id(inst0))

2voto

John Punkte 14038

Da ich relativ neu in Python bin, bin ich mir nicht sicher, was das gängigste Idiom ist, aber das Einfachste, was mir einfällt, ist die Verwendung eines Moduls anstelle einer Klasse. Was in Ihrer Klasse Instanzmethoden gewesen wären, werden im Modul zu Funktionen, und alle Daten werden im Modul zu Variablen, anstatt zu Mitgliedern der Klasse. Ich vermute, dass dies der pythonische Ansatz ist, um die Art von Problemen zu lösen, für die Leute Singletons verwenden.

Wenn Sie wirklich eine Singleton-Klasse wollen, gibt es eine vernünftige Implementierung, die in der erster Treffer bei Google für "Python Singleton", genauer gesagt:

class Singleton:
    __single = None
    def __init__( self ):
        if Singleton.__single:
            raise Singleton.__single
        Singleton.__single = self

Das scheint zu genügen.

2voto

Tiezhen Punkte 113

Meine einfache Lösung, die auf dem Standardwert der Funktionsparameter basiert.

def getSystemContext(contextObjList=[]):
    if len( contextObjList ) == 0:
        contextObjList.append( Context() )
        pass
    return contextObjList[0]

class Context(object):
    # Anything you want here

2voto

neu-rah Punkte 1661

Singletons Halbbruder

Ich stimme staale voll und ganz zu und hinterlasse hier ein Beispiel für die Erstellung eines einzigen Halbbruders:

class void:pass
a = void();
a.__class__ = Singleton

a meldet nun, dass es zur gleichen Klasse wie Singleton gehört, auch wenn es nicht so aussieht. So Singletons mit komplizierten Klassen am Ende abhängig von wir nicht viel mit ihnen verwirren.

Da dies so ist, können wir den gleichen Effekt erzielen und einfachere Dinge wie eine Variable oder ein Modul verwenden. Wenn wir jedoch aus Gründen der Klarheit Klassen verwenden wollen und weil in Python ist eine Klasse ein Objekt Wir haben also bereits das Objekt (nicht und Instanz, aber es wird genau so tun).

class Singleton:
    def __new__(cls): raise AssertionError # Singletons can't have instances

Dort haben wir einen netten Assertion-Fehler, wenn wir versuchen, eine Instanz zu erstellen, und wir können auf Ableitungen statische Mitglieder speichern und Änderungen an ihnen zur Laufzeit vornehmen (ich liebe Python). Dieses Objekt ist so gut wie andere Halbbrüder (Sie können sie immer noch erstellen, wenn Sie möchten), aber es wird aufgrund der Einfachheit tendenziell schneller laufen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X