Python: абстрактный экземпляр переменной? - PullRequest
0 голосов
/ 27 июня 2018

Есть ли способ объявить абстрактную переменную экземпляра для класса в Python?

Например, у нас есть абстрактный базовый класс Bird, с абстрактным методом fly, реализованным с использованием пакета abc, и абстрактной переменной экземпляра feathers (что я ищу), реализованной как собственность.

from abc import ABCMeta, abstractmethod

class Bird(metaclass=ABCMeta):

    @property
    @abstractmethod
    def feathers(self):
        """The bird's feathers."""

    @abstractmethod
    def fly(self):
        """Take flight."""

Проблема в том, что Eagle, класс, производный от Bird, должен иметь feathers, реализованный как метод свойства. Поэтому следующий класс не является приемлемым, но я бы хотел, чтобы он был

class Eagle(Bird):

    def __init__(self):
        self.feathers = 'quill'

    def fly(self):
        print('boy are my arms tired')

Может возникнуть проблема, поскольку требование касается самого экземпляра и действительно после его создания, поэтому я не знаю, будут ли работать такие вещи, как пакет abc.

Существуют ли стандартные способы справиться с этим?

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

Система abc не включает способ объявления абстрактной переменной экземпляра. Код, который определяет, является ли класс конкретным или абстрактным, должен выполняться до того, как будут созданы какие-либо экземпляры; он может достаточно легко проверить класс на наличие методов и свойств, но не может определить, будут ли экземпляры иметь какой-либо конкретный атрибут экземпляра.

Самая близкая вещь, вероятно, является переменной аннотацией:

class Bird(metaclass=ABCMeta):
    feathers : str
    ...

abc не будет ничего делать с этой аннотацией, но она, по крайней мере, выражает читателям и средствам проверки статического типа, что экземпляры Bird должны иметь переменную экземпляра feathers. (Будут ли статические контролеры типов понимать, что эта переменная экземпляра должна происходить из подклассов, я не знаю.)

0 голосов
/ 27 июня 2018

Может работать что-то простое, подобное следующему, используя общее свойство:

class Bird(object):
    @property
    def feathers(self):
        try:
            return self._feathers
        except AttributeError:
            raise WhateverError('No feathers')  # maybe obfuscate inner structure

class Eagle(Bird):
    def __init__(self):
        self._feathers = 'quill'

>>> Bird().feathers
WhateverError: No feathers
>>> Eagle().feathers
'quill'
...