En mis esfuerzos como aprendiz de pitón me quedé atrapado recientemente en algún comportamiento extraño (desde mi punto de vista) si traté de trabajar con atributos de clase. No me quejo, pero agradeceré algunos comentarios útiles para arrojar algo de luz sobre este tema.python: ¿atributo de clase/herencia variable con polimorfismo?
Para reducir un asunto complejo en una pregunta más concisa i formularía así:
Cuál es la forma "Pythonic" para asegurarse de que un atributo de clase se comporta más como una variable estática en un árbol de herencia?
Me parece que un atributo de clase se comporta como un valor predeterminado de "copia en lectura" con características polimórficas. Mientras haga operaciones de "solo lectura", se mantendrá como "singleton", , pero tan pronto como acceda al atributo de clase con una asignación a través de la clase o instancia derivada, se transforma en una nueva referencia perdiendo la relación con la referencia base heredada.
(tiene seguro de potencial de algunas de las características interessting, pero hay que entenderlo a abrazarla, por lo que una idea es muy apreciada.)
class A(object):
classvar = 'A'
def setclassvar(self, value):
A.classvar = value
def __str__(self):
return "%s id(%s) " %(A.classvar, hex(id(A.classvar))[2:-1].upper())
class A1(A):
pass
class B(object):
classvar = 'B'
def setclassvar(self, value):
self.__class__.classvar = value
def __str__(self):
cvar = self.__class__.classvar
return "%s id(%s) " %(cvar, hex(id(cvar))[2:-1].upper())
class B1(B):
def setclassvar(self, value):
self.__class__.classvar = value
a, a1 = A(), A1()
a1.setclassvar('a')
print "new instance A: %s" %a
print "new instance A1: %s" %a
b, b1 = B(), B1()
b1.setclassvar('bb')
print "new instance B: %s" %b
print "new instance B1: %s" %b1
a1.setclassvar('aa')
print "new value a1: %s" %a
print "new value a: %s" %a
a1.classvar = 'aaa'
print "direct access a1: %s id(%s)" %(a1.classvar, hex(id(a1.classvar))[2:-1].upper())
print "method access a1: %s" %a1
print "direct access a: %s" %a
produce lo siguiente:
new instance A: a id(B73468A0) new instance A1: a id(B73468A0) new instance B: B id(B73551C0) new instance B1: bb id(AD1BFC) new value a1: aa id(AD1BE6) new value a: aa id(AD1BE6) direct access a1: aaa id(A3A494) method access a1: aa id(AD1BE6) direct access a: aa id(AD1BE6)
Por lo tanto, el acceso directo (asignación) object.classvar
o mediado a través de self.__class__.classvar
no es el lo mismo que BASECLASS.classvar
.
Este es un problema de alcance o algo totalmente diferente.
Esperamos sus respuestas y gracias de antemano. :-)
Edición: Hubo una respuesta para un tiempo muy corto lo que sugiere el uso de la clase-descriptores como: How to make a class property?.
desgracia que no parece funcionar:
class Hotel(Bar):
def __init__(self):
Hotel.bar += 1
hotel = Hotel()
assert hotel.bar == 51
assert hotel.bar == foo.bar
La segunda aserción falla! hotel.bar no hace referencia al mismo objeto como foo.bar
y hotel.bar
referencias a otra cosa que a Hotel.bar!
segunda edición: yo soy muy consciente de que singletons se consideran un "anti patrón" y no tienen la intención de utilizarlos (extensivly). Por lo tanto, no los mencioné en la pregunta-titel. Aun así hay muchas soluciones que discuten y brindan soluciones con y sobre singletons, mi pregunta permanece: ¿Por qué una variable de clase puede separar su referencia tan fácilmente? Rubí se comporta más como se siente natural para mí: http://snippets.dzone.com/posts/show/6649
Busque Python Singleton. (a) esto ha sido respondido y (b) por lo general, es una muy mala idea tratar de hacer Singletons. http://stackoverflow.com/search?q=python+singleton –
posible duplicado de [Creación de un singleton en python] (http://stackoverflow.com/questions/6760685/creating-a-singleton-in-python) –
No estoy interesado en una discusión "antipatrina", así que por favor tengan paciencia conmigo en este tema, pero evitaron el problema de la herencia. Todas las soluciones que investigué no abordaron la característica polimórfica de una asignación, que mata a la referencia original. Ruby por otro lado, hace lo que parece más "natural" para mí (pero obviamente no para los demás): http://snippets.dzone.com/posts/show/6649. Así que supongo que es un tema de alcance de nombre o similar, pero todavía me estoy preguntando. –