如何在Python 3.4+中写入抽象属性

Bor*_*ora 2 python inheritance abstract-class python-3.x

在Python 3.6中,假设我有一个抽象类 MyAbstractClass

from abc import ABC, abstractmethod

class MyAbstractClass(ABC):

    @property
    @abstractmethod
    def myProperty(self):
        pass
Run Code Online (Sandbox Code Playgroud)

并且有一个类MyInstantiatableClass继承自它。那么,如何myProperty在此类实例化对象时写入属性?我希望既可以设置又可以获取myProperty。以下无效。

from MyAbstractClass import MyAbstractClass

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

    @myProperty.setter
    def myProperty(self, desiredValueOfMyProperty): # value coming from __init__
        self._myProperty = desiredValueOfMyProperty
Run Code Online (Sandbox Code Playgroud)

还有一个主要功能

from MyInstantiatableClass import MyInstantiatableClass

def main():
    MyInstantiatableClass(3) # 3 is the desiredValueOfMyProperty for this instantiation
    MyInstantiatableClass(5) # 5 is the desiredValueOfMyProperty for this instantiation
Run Code Online (Sandbox Code Playgroud)

Jim*_*ard 5

看来这里有出入。使用@property@abstractmethod似乎并没有强制从abc继承的类需要定义settergetter。使用这个:

@property
@abstractmethod
def myProperty(self):
    pass

@myProperty.setter
@abstractmethod
def myProperty(self):
    pass
Run Code Online (Sandbox Code Playgroud)

然后仅为getter类中的作品提供实现,并允许实例化:

@property
def myProperty(self):
    return self._myProperty
Run Code Online (Sandbox Code Playgroud)

这是由于myProperty在ABC的命名空间中仅出现一个名称(),因此在基类中进行覆盖时,只需定义一个名称即可。

有一种解决方法可以强制执行。您可以创建单独的抽象方法并将其property直接传递给:

class MyAbstractClass(ABC):

    @abstractmethod
    def getProperty(self):
        pass

    @abstractmethod
    def setProperty(self, val):
        pass

    myAbstractProperty = property(getProperty, setProperty)
Run Code Online (Sandbox Code Playgroud)

提供了一个实现这个ABC现在需要getter并且setter有一个执行(已被列为这两个名字abstractmethod以s MyAbstractClass命名空间需要有一个实现):

class MyInstantiatableClass(MyAbstractClass):

    def getProperty(self):
        return self._Property

    def setProperty(self, val):
        self._Property = val
    myAbstractProperty = property(getProperty, setProperty)
Run Code Online (Sandbox Code Playgroud)

实现它们与任何旧属性完全相同。那里没有区别。