AttributeError: el objeto ‘propiedad’ no tiene atributo

Python (2.6) parece estar disminuyendo sin ninguna razón, ¿alguien puede ver un problema con este código?

class DB (): def doSomething (self, str): print str class A (): __db = DB() @staticmethod def getDB (): return A.__db db = property(getDB) A.db.doSomething("blah") 

Falla con la excepción:

AttributeError: el objeto ‘propiedad’ no tiene atributo ‘doSomething’

Tenía entendido que una propiedad ejecutaría automáticamente su captador cuando se accediera, así que ¿por qué se queja de un objeto de propiedad y por qué no encuentra mi método claramente disponible?

Además de la necesidad de heredar de un object , las propiedades solo funcionan en instancias.

 a = A() a.db.doSomething("blah") 

Para hacer que una propiedad funcione en la clase, puede definir una metaclase. (Una clase es una instancia de una metaclase, por lo que las propiedades definidas en la metaclase funcionan en la clase, al igual que las propiedades definidas en una clase funcionan en una instancia de esa clase).

No estás usando las clases correctamente. Una clase es (normalmente) dos cosas:

  1. Una fábrica para crear una familia de objetos relacionados.
  2. Una definición del comportamiento común de esos objetos.

Estos objetos relacionados son las instancias de la clase. Los métodos normales se invocan en instancias de la clase, no en la clase en sí. Si desea métodos que se pueden invocar desde la clase, sin una instancia, necesita etiquetar los métodos con @classmethod (o @staticmethod ).

Sin embargo, en realidad no sé si las propiedades funcionan cuando se recuperan de un objeto de clase. No puedo comprobar ahora, pero no lo creo. El error que está obteniendo es que A.db está recuperando el objeto de propiedad que define la propiedad en sí, no está “evaluando” la propiedad para obtener A.__db . Los objetos de propiedad no tienen atributo doSomething . Las propiedades están diseñadas para ser creadas en clases como descripciones de cómo funcionan las instancias de esas clases.

Si tenía la intención de trabajar con una instancia de A, deberá crear una:

 my_a = A() my_a.db.doSomething("blah") 

Sin embargo, esto también fallará. No has escrito correctamente getDB como ningún tipo de método. Los métodos normales necesitan un argumento para representar la instancia en la que se invocó (tradicionalmente llamado self ):

 def getDB(self): ... 

Los métodos estáticos no, pero necesitan un decorador para etiquetarlos como estáticos:

 @staticmethod def getDB(): ... 

Los métodos de clase necesitan tanto un argumento para recibir la clase en la que fueron invocados como un decorador:

 @classmethod def getDB(cls): ... 

No necesitas captadores en Python:

 class B(object): def do_something(self, str): print str class A(object): db = B() A.db.do_something("blah") 

(Yo también PEP8: ed el código)