2012-02-07 8 views
6

general:objetos anidados y setattr y getattr (sí, es esa época)

class Inner(object): 
    def __init__(self, x): 
     self.x = x 

class Outer(object): 
    def __init__(self, z): 
     self.inner = Inner(z) 

o = Outer(10) 

Ahora, quiero que el objeto externo a comportarse de forma transparente - los atributos establecidos en o deberían ser enumerados en o.inner, lo mismo para leyendo: o.something debería devolver, de hecho, el valor de o.inner.sommething. Algo así como un proxy o un relevo.

__getattr__ para Outer parece simple & obras:

def __getattr__(self, item): 
    return getattr(self, item) 

¿cómo iba a manejar __setattr__? No pude encontrar nada que no causara un error de recursión y hacerme odiarme a mí mismo.

¿O es el concepto mismo defectuoso?

(Otro enfoque Probé estaba haciendo Outer una subclase de Inner - esto realmente no jugar estéticamente la presente @classmethods, por no mencionar el IDE se perdería dentro de esos -. No es capaz de resolver algunos atributos Dejemos eso por ahora, ¿quizás?)

+0

¿Querías 'self.inner = Inner (z)'? Además, ¿su método getattr devuelve datos de Inner()? Tal como está escrito, parece que solo haría referencia a Outer. – gfortune

+0

Sí, regresa. Corregido ambos, gracias! – ntl0ve

Respuesta

7

La parte engañosa es establecer el atributo inner de la clase Outer correctamente. Lo que puede hacer es llamar al método de object__setattribute__ (clase base de Outer):

class Inner(object): 
    def __init__(self, x): 
     self.x = x 

class Outer(object):  
    def __init__(self, z): 
     object.__setattr__(self, 'inner', Inner(z)) 

    def __getattr__(self, name): 
     return getattr(self.inner, name) 

    def __setattr__(self, name, value): 
     return setattr(self.inner, name, value) 

Ahora, funciona correctamente:

o = Outer(10) 
print o.x  # 10 
print o.inner.x # 10 
o.g = 3 
print o.g  # 3 
print o.inner.g # 3 

Sin embargo, no está claro a mi por qué no lo hace quiero usar herencia en este caso. Parece más natural y pitónico tener Outer heredar de Inner.

+0

Y el motivo por el que print (o.inner) funciona es porque o.inner ya existe, por lo que no llama a '__getattr__' y trata de devolver o.inner.inner, ¿correcto? No es obvio que '__getattr__' no se llame en los casos en que el elemento solicitado ya existe como parte del objeto en cuestión. – gfortune

+0

@gfortune, sí; para más información, vea [esta pregunta] (http://stackoverflow.com/questions/3278077/difference-between-getattr-vs-getattribute-in-python). – senderle

+0

sí, consulte [\ _ \ _ getattr \ _ \ _] (http://docs.python.org/reference/datamodel.html#object.__getattr__) documentos – jterrace

Cuestiones relacionadas