2011-05-11 7 views
43

Dans le code suivant, je crée une classe abstraite de base Base. Je veux que toutes les classes qui héritent de Base fournissent la propriété name, j'ai donc fait de cette propriété un @abstractmethod.Comment créer des propriétés abstraites dans les classes abstraites python

Puis j'ai créé une sous-classe de Base, appelée Base_1, qui est censée fournir certaines fonctionnalités, tout en restant abstraite. Il n'y a pas de propriété dans Base_1, mais néanmoins python instaure un objet de cette classe sans erreur. Comment créer des propriétés abstraites?

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 vous oubliez d'utiliser décorateur '@' property' dans la classe C', 'name' va revenir à une méthode. – kevinarpe

Répondre

3

Depuis Python 3.3 un bug a été corrigé qui signifie que le décorateur property() est maintenant correctement identifié comme abstrait lorsqu'il est appliqué à une méthode abstraite.

De python docs:

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

Jusqu'à Python 3.3, vous ne pouvez pas imbriquer @abstractmethod et @property. Utilisez @abstractproperty pour créer des propriétés abstraites (docs).

from abc import ABCMeta, abstractmethod, abstractproperty 

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

Le code soulève maintenant l'exception correcte:

 
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 fait cette réponse est fausse pour les pythons plus jeunes: depuis 3.3, '@ abstractproperty' est déprécié au profit d'une combinaison comme OP. –

+10

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

+0

merci, codeape. Je mettrai à jour la réponse en conséquence. –