2011-05-11 11 views
43

En el siguiente código, creo una clase abstracta base Base. Quiero que todas las clases que hereden de Base proporcionen la propiedad name, por lo que hice de esta propiedad un @abstractmethod.Cómo crear propiedades abstractas en las clases abstractas de Python

Luego creé una subclase de Base, llamada Base_1, que está destinada a proporcionar alguna funcionalidad, pero que aún permanece abstracta. No hay una propiedad name en Base_1, pero sin embargo, python instaura un objeto de esa clase sin un error. ¿Cómo se crean propiedades abstractas?

from abc import ABCMeta, abstractmethod 
class Base(object): 
    __metaclass__ = ABCMeta 
    def __init__(self, strDirConfig): 
     self.strDirConfig = strDirConfig 

    @abstractmethod 
    def _doStuff(self, signals): 
     pass 

    @property  
    @abstractmethod 
    def name(self): 
     #this property will be supplied by the inheriting classes 
     #individually 
     pass 


class Base_1(Base): 
    __metaclass__ = ABCMeta 
    # this class does not provide the name property, should raise an error 
    def __init__(self, strDirConfig): 
     super(Base_1, self).__init__(strDirConfig) 

    def _doStuff(self, signals): 
     print 'Base_1 does stuff' 


class C(Base_1): 
    @property 
    def name(self): 
     return 'class C' 


if __name__ == '__main__': 
    b1 = Base_1('abc') 
+0

Gotcha: Si olvidó usar decorador '@ property' en clase 'C',' name' volverá a un método. – kevinarpe

Respuesta

3

Desde Python 3.3 un error se corrigió lo que significa que el decorador property() ahora se identifica correctamente como abstracta cuando se aplica a un método abstracto.

De python docs:

class C(ABC): 
    @property 
    @abstractmethod 
    def my_abstract_property(self): 
     ... 
34

Hasta Python 3.3, no se pueden anidar @abstractmethod y @property.

Utilice @abstractproperty para crear propiedades abstractas (docs).

from abc import ABCMeta, abstractmethod, abstractproperty 

class Base(object): 
    # ... 
    @abstractproperty 
    def name(self): 
     pass 

El código ahora plantea la excepción correcta:

 
Traceback (most recent call last): 
    File "foo.py", line 36, in 
    b1 = Base_1('abc') 
TypeError: Can't instantiate abstract class Base_1 with abstract methods name 
+28

en realidad esta respuesta es incorrecta para pitones más jóvenes: desde 3.3, '@ abstractproperty' está en desuso en favor de una combinación como OP's. –

+10

De los 3.3 documentos: http://docs.python.org/3/library/abc.html#abc.abstractproperty – codeape

+0

gracias, codeape. actualizaré la respuesta en consecuencia. –

Cuestiones relacionadas