2009-06-16 18 views
7

En la clase B a continuación, quería llamar a la función __set__ en la clase A siempre que asigne un valor a B().a. En cambio, establecer un valor en B().a sobrescribe B().a con el valor. La asignación de Clase C a C().a funciona correctamente, pero quería tener una instancia separada de A para cada clase de usuario, es decir, no quiero cambiar 'a' en una instancia de C() para cambiar 'a' en todas las demás instancias. Escribí un par de pruebas para ayudar a ilustrar el problema. ¿Pueden ayudarme a definir una clase que pase tanto test1 como test2?¿Por qué declarar una clase de descriptor en la función __init__ rompe la funcionalidad del descriptor?

class A(object): 
    def __set__(self, instance, value): 
     print "__set__ called: ", value 

class B(object): 
    def __init__(self): 
     self.a = A() 

class C(object): 
    a = A() 

def test1(class_in): 
    o = class_in() 
    o.a = "test" 
    if isinstance(o.a, A): 
     print "pass" 
    else: 
     print "fail" 

def test2(class_in): 
    o1, o2 = class_in(), class_in() 
    if o1.a is o2.a: 
     print "fail" 
    else: 
     print "pass" 

Respuesta

4

consiguiente a la documentation:

Los siguientes métodos sólo se aplican cuando una instancia de la clase que contiene el método (un descriptor de llamada clase) aparece en la clase diccionario de otra nueva clase de estilo, conocida como la clase propietaria. En los ejemplos a continuación, "el atributo" hace referencia al atributo cuyo nombre es la clave de la propiedad en la clase de propietario '__dict__. Los descriptores solo se pueden implementar como las clases de estilo nuevo .

Así que no puede tener descriptores en las instancias.

Sin embargo, desde el descriptor consigue un árbitro la instancia que se utiliza para acceder a ella, sólo tiene que utilizar como una clave para el almacenamiento de estado y se puede tener un comportamiento diferente en función de la instancia.

+0

OK, puedo vivir con eso – user83753

+0

Pensándolo bien, tal vez no pueda vivir con eso. En mi aplicación, quiero poner funciones de miembro en A que también dependen del estado de la clase propietaria. Por ejemplo: Propietario (información del estado) Propietario.a = datos Propietario.a.foo() ¿Cómo obtiene foo la información de estado del propietario? – user83753

+0

@unknown (google): ah, para eso almacena los datos en la instancia en sí. Entonces puedes buscarlo desde los métodos. – nosklo

0

Aquí hay una clase que puede aprobar las pruebas originales, pero no intentes usarla en la mayoría de las situaciones. ¡falla la prueba de instancia en sí misma!

class E(object): 
    def __new__(cls, state): 
     class E(object): 
      a = A(state) 
      def __init__(self, state): 
       self.state = state 
     return E(state) 

#>>> isinstance(E(1), E) 
#False 
+0

que es una función de fábrica de clase, disfrazada como una clase – nosklo

+0

Sí, y está orgullosa de ello. – user83753

0

Fui mordido por un problema similar en el sentido de que quería clasificar objetos con atributos gobernados por un descriptor. Cuando hice esto, noté que los atributos se sobrescribían en todos los objetos de forma tal que no eran individuales.

me planteó una cuestión SO y la respuesta resultante es aquí: class attribute changing value for no reason

Un buen enlace del documento discutir descriptores está aquí: http://martyalchin.com/2007/nov/24/python-descriptors-part-2-of-2/

Un descriptor de ejemplo desde el enlace mencionado es a continuación:

class Numberise(object): 
    def __init__(self, name): 
     self.name = name 

    def __get__(self, instance, owner): 
     if self.name not in instance.__dict__: 
      raise (AttributeError, self.name) 
     return '%o'%(instance.__dict__[self.name]) 

    def __set__(self, instance, value): 
     print ('setting value to: %d'%value) 
     instance.__dict__[self.name] = value 
Cuestiones relacionadas