2009-04-14 13 views
7

Ich habe Probleme bei der Implementierung eines Borg in Python. Ich habe ein Beispiel in einer Antwort auf this question gefunden, aber es funktioniert nicht für mich, es sei denn, ich vermisse etwas. Hier ist der Code:Python Borg Muster Problem


class Config: 
    """ 
    Borg singleton config object 
    """ 
    __we_are_one = {} 
    __myvalue = "" 

    def __init__(self): 
     #implement the borg pattern (we are one) 
     self.__dict__ = self.__we_are_one 
     self.__myvalue = "" 

    def myvalue(self, value=None): 
     if value: 
      self.__myvalue = value 
     return self.__myvalue 

conf = Config() 
conf.myvalue("Hello") 
conf2 = Config() 
print conf2.myvalue() 

Ich nehme an, dies bedeutet „Hallo“ zu drucken, aber für mich ist es druckt nur eine leere Zeile. Irgendwelche Ideen warum das sein könnte?

+1

Warum verwenden Sie doppelte __ Namen für Ihre Attribute? Ein einzelnes führendes _ wird tun, um es "privat" zu machen. –

+0

Nun, ich kopierte den Code von der anderen Frage, mit der ich verlinkt habe. Aber irgendwie dachte ich, dass ein einzelnes _ deutete an, dass es privat ist, während ein doppelt _ verursacht, dass ein Mangel an Namen, der ein noch stärkerer Hinweis ist, dass es * wirklich * privat ist, obwohl es immer noch zugegriffen werden kann, wenn der Benutzer bestimmt ist. – chrism1

+2

Nein! Einzelne führende Unterstriche machen sie NICHT privat, sondern machen es so, dass Variablen auf Modulebene nicht in 'von foo import *' importiert werden. Ansonsten hat sie keinen anderen Effekt, als auf die Privatsphäre zu "hinweisen". –

Antwort

13

Es sieht aus wie es funktioniert eher zu gut :-)

Das Problem ist, dass die Zuordnung self.__myvalue = "" in __init__ wird immer den Wert von myvalue ein neuer Borg jedes Mal, verprügeln ist, äh, erstellt. Sie können das sehen, wenn Sie einige zusätzliche Druckanweisungen zu Ihrem Test hinzufügen:

conf = Config() 
conf.myvalue("Hello") 
print conf.myvalue() # prints Hello 
conf2 = Config() 
print conf.myvalue() # prints nothing 
print conf2.myvalue() # prints nothing 

die self.__myvalue und Dinge entfernen wird gut.

Having said that, ist die Implementierung von myvalue() ein wenig seltsam. Besser, würde ich sagen, explizite Getters und Setter verwenden Eigenschaften. Sie wollen auch einen Code in __init__, um den Wert myvalue zu initialisieren, wenn es noch nicht existiert, oder zumindest damit umzugehen, dass es möglicherweise nicht im Getter existiert. Vielleicht so etwas wie:

class Config(object): 
    """ 
    Borg singleton config object 
    """ 
    _we_are_one = {} 

    def __init__(self): 
     #implement the borg pattern (we are one) 
     self.__dict__ = self._we_are_one 

    def set_myvalue(self, val): 
     self._myvalue = val 

    def get_myvalue(self): 
     return getattr(self, '_myvalue', None) 

    myvalue = property(get_myvalue, set_myvalue) 

c = Config() 
print c.myvalue # prints None 
c.myvalue = 5 
print c.myvalue # prints 5 
c2 = Config() 
print c2.myvalue #prints 5 
+0

Ha! Ziemlich offensichtlich, sollte es entdeckt haben. Danke für die Tipps alle. – chrism1

+0

Ich dachte, dass diese Borg-Implementierung nicht mit neuen Stilklassen funktioniert. Fehle ich etwas? – legesh

+0

@legesh scheint in Python 2.6 gut zu funktionieren. Vielleicht vermisse ich etwas ... Welche Informationen oder Erfahrungen lassen Sie bei neuen Unterrichtsstunden pausieren? –

1

Das Problem scheint, dass init() myvalue auf eine leere Zeichenfolge zurückgesetzt wird. Wenn ich diese Zeile entferne, bekomme ich die erwartete Ausgabe.

4

die Entfernung von self.__myvalue = "" mit den new-style Borg Kombination und die Vorschläge __ in Variablennamen zu vermeiden, erhalten wir:

class Config(object): 
    """ 
    Borg singleton config object 
    """ 
    _we_are_one = {} 
    _myvalue = "" 

    def __new__(cls, *p, **k): 
     self = object.__new__(cls, *p, **k) 
     self.__dict__ = cls._we_are_one 
     return self 

    def myvalue(self, value=None): 
     if value: 
      self._myvalue = value 
     return self._myvalue 

if __name__ == '__main__': 
    conf = Config() 
    conf.myvalue("Hello") 
    conf2 = Config() 
    print conf2.myvalue() 
1
class Borg(object): 
    """Demonstrating the Borg-pattern: All the instances of a class already 
    know what one of them learned... Scary, isn't it?""" 

    def __init__(self, name): 
     self.name = name 

    @classmethod 
    def borg_knowledge(cls, who_is_it): 
     if hasattr(cls, "b_knowledge"): 
      return "%s: I already know that the borg pattern is awesome!" % who_is_it 
     else: 
      cls.b_knowledge = True 
      return "%s: Learning about the borg pattern..." % who_is_it 

    def personal_experience(self): 
     if hasattr(self, "p_knowledge"): 
      return "%s: I already know that!" % self.name 
     else: 
      self.p_knowledge = True 
      return "%s: Learning something..." % self.name 


b1 = Borg("b1") 
b2 = Borg("b2") 
print ">> Created b1 and b2, both Borg"; print 

print ">> Usual class behavior. One instance does not know what the other does." 
print b1.personal_experience() 
print b2.personal_experience() 

print 
print ">> Borg have a shared knowledge a.k.a. why classmethods are different!" 
print b1.borg_knowledge(b1.name) 
print b2.borg_knowledge(b2.name) 
0
> The problem appears to be that init() is resetting myvalue to an 
> empty string. When You remove that 
> line ('self.__myvalue = ""') then you will get the expected 
> output. 
0

Ich habe versucht, diese Umsetzung mit der "alte Stil" sowie der "neue Stil" und ich kann keinen Unterschied zwischen ihnen sehen. Gibt es einen Vorteil gegenüber dem anderen? Oder sind diese grundsätzlich gleichwertig?

class Borg(object): 
    shared_state = {'a_value': True} 
    def __init__(self): 
     self.__dict__ = self.shared_state 


class NewBorg(object): 
    shared_state = {'a_value': True} 

    def __new__(cls, *p, **k): 
     self = object.__new__(cls, *p, **k) 
     self.__dict__ = cls.shared_state 
     return self 


borg_a = Borg() 
borg_b = Borg() 

print id(borg_a), '!=', id(borg_b) 
assert borg_a.shared_state == borg_b.shared_state 
borg_a.shared_state['a_value'] = False 
assert borg_a.shared_state == borg_b.shared_state 

new_borg_a = NewBorg() 
new_borg_b = NewBorg() 

print id(new_borg_a), '!=', id(new_borg_b) 
assert new_borg_a.shared_state == new_borg_b.shared_state 
new_borg_a.shared_state['a_value'] = False 
assert new_borg_a.shared_state == new_borg_b.shared_state