2009-04-14 20 views
7

Tengo problemas para implementar un borg en python. Encontré un ejemplo en una respuesta al this question pero no funciona para mí, a menos que me falta algo. Aquí está el código:Problema con el patrón de bordado Python


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() 

Asumo esto está destinado a imprimir "Hola", pero para mí sólo imprime una línea en blanco. ¿Alguna idea de por qué esto podría ser?

+1

¿Por qué usa nombres dobles __ para sus atributos? Una única línea _ hará para que sea "privada". –

+0

Bueno, copié el código de la otra pregunta a la que me he vinculado. Pero, de todos modos, pensé que un solo _ insinuaba que era privado, mientras que un doble _ causaba un cambio de nombre que es una pista aún más fuerte de que * realmente * es privado, aunque todavía se puede acceder si se determina al usuario. – chrism1

+2

¡No! Los caracteres de subrayado iniciales NO los harán privados, solo haga que las variables de nivel de módulo no se importen en 'de importación foo *' De lo contrario, no tiene otro efecto que el de 'insinuar' la privacidad. –

Respuesta

13

Parece que está funcionando bien sobra :-)

La cuestión es que la asignación self.__myvalue = "" en __init__ siempre clobber el valor de myvalue cada vez que un nuevo Borg es, er, creada. Esto se puede ver si se agregan algunas declaraciones de impresión adicionales al ensayo:

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

Retire los self.__myvalue y las cosas van a estar bien.

Habiendo dicho eso, la implementación de myvalue() es un poco rara. Mejor, diría yo, tener getters y setters explícitos usando propiedades. También querrá un código en __init__ para inicializar el valor de myvalue si aún no existe, o para manejar al menos que podría no existir en el getter. Tal vez algo como:

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

¡Ja! Bastante obvio en realidad, debería haberlo detectado. Gracias por todos los consejos. – chrism1

+0

Pensé que esta implementación de Borg no funciona con las clases de estilo nuevo. ¿Me estoy perdiendo de algo? – legesh

+0

@legesh Parece funcionar bien en Python 2.6. Tal vez me falta algo ... ¿qué información o experiencia te da pausa con las clases de nuevo estilo? –

1

El problema parece ser que init() está restableciendo myvalue en una cadena vacía. Cuando elimino esa línea, obtengo el resultado esperado.

4

La combinación de la eliminación de self.__myvalue = "" con los new-style Borg y las sugerencias para evitar __ en los nombres de variables, obtenemos:

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

he intentado implementar esta usando el "viejo estilo" así como el "nuevo estilo" y no puedo ver una diferencia entre ellos. ¿Hay una ventaja para uno sobre el otro? ¿O son básicamente equivalentes?

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 
Cuestiones relacionadas