2017-06-05 1 views
0

En Python 3.6, Disons que j'ai une classe abstraite MyAbstractClassComment écrire à une propriété abstraite en Python 3.4+

from abc import ABC, abstractmethod 

class MyAbstractClass(ABC): 

    @property 
    @abstractmethod 
    def myProperty(self): 
     pass 

et une classe MyInstantiatableClass en héritent. Alors, comment écrire sur la propriété myProperty lors de l'instanciation d'un objet de cette classe? J'aimerais pouvoir définir et obtenir myProperty. Ci-dessous ne fonctionne pas.

from MyAbstractClass import MyAbstractClass 

class MyInstantiatableClass(MyAbstractClass): 
    def __init__(self, desiredValueOfMyProperty): 
     ???? 

    @myProperty.setter 
    def myProperty(self, desiredValueOfMyProperty): # value coming from __init__ 
     self._myProperty = desiredValueOfMyProperty 

Et une fonction principale, par exemple,

from MyInstantiatableClass import MyInstantiatableClass 

def main(): 
    MyInstantiatableClass(3) # 3 is the desiredValueOfMyProperty for this instantiation 
    MyInstantiatableClass(5) # 5 is the desiredValueOfMyProperty for this instantiation 
+2

Implémentez-vous _only_ le setter, sans getter? –

+0

J'aimerais pouvoir définir et obtenir 'myProperty' à' MyInstantiatableClass'. – Bora

+0

Définissez la propriété de la même manière que vous le feriez normalement. – user2357112

Répondre

3

Il semble qu'il y ait une différence ici; en utilisant @property avec @abstractmethod ne semble pas appliquer les classes qui héritent de votre abc pour définir à la fois setter et getter. En utilisant ceci:

@property 
@abstractmethod 
def myProperty(self): 
    pass 

@myProperty.setter 
@abstractmethod 
def myProperty(self): 
    pass 

et fournir une mise en œuvre que pour la getter dans les travaux de classe et permet instanciation:

@property 
def myProperty(self): 
    return self._myProperty 

Cela est dû au fait que seul un nom (myProperty) apparaît dans l'espace de nom de l'ABC, lorsque vous remplacez dans la classe de base, vous avez seulement besoin de définir ce nom.

Il y a un moyen de contourner cela qui l'impose. Vous pouvez créer des méthodes abstraites distinctes et les transmettre à property directement:

class MyAbstractClass(ABC): 

    @abstractmethod 
    def getProperty(self): 
     pass 

    @abstractmethod 
    def setProperty(self, val): 
     pass 

    myAbstractProperty = property(getProperty, setProperty) 

Fournir une mise en œuvre de cette abc requiert désormais getter et setter d'avoir une mise en œuvre (les deux noms qui ont été répertoriés comme abstractmethod s dans MyAbstractClass espace de noms besoin d'avoir une implémentation):

class MyInstantiatableClass(MyAbstractClass): 

    def getProperty(self): 
     return self._Property 

    def setProperty(self, val): 
     self._Property = val 
    myAbstractProperty = property(getProperty, setProperty) 

Les implémenter est exactement la même chose que n'importe quelle ancienne propriété. Il n'y a pas de différence là-bas.

+0

La propriété abstraite n'a pas besoin d'utiliser '.setter', et la spécification de' .setter' sur la propriété abstraite ne forcera pas l'implémentation concrète à avoir un setter ou quelque chose comme ça. – user2357112

+0

@ user2357112 Je ne m'attendais pas à ça, c'est vrai. Vous pouvez apparemment forcer l'implémentation à définir les deux en passant directement 'abstractmethods' à' property'. –