Разница между абстрактным классом и интерфейсом в Python



в чем разница между абстрактным классом и интерфейсом в Python?

779   6  

6 ответов:

иногда вы увидите следующее:

class Abstract1( object ):
    """Some description that tells you it's abstract,
    often listing the methods you're expected to supply."""
    def aMethod( self ):
        raise NotImplementedError( "Should have implemented this" )

и разница между абстрактным и интерфейсом-это вещь для волос когда у вас есть утка набрав.

Java использует интерфейсы, потому что он не имеет множественного наследования.

поскольку Python имеет множественное наследование, вы также можете увидеть что-то вроде этого

class SomeAbstraction( object ):
    pass # lots of stuff - but missing something

class Mixin1( object ):
    def something( self ):
        pass # one implementation

class Mixin2( object ):
    def something( self ):
        pass # another

class Concrete1( SomeAbstraction, Mixin1 ):
    pass

class Concrete2( SomeAbstraction, Mixin2 ):
    pass

Это использует своего рода абстрактный суперкласс с миксинами для создания конкретных подклассов, которые являются непересекающимися.

в чем разница между абстрактным классом и интерфейсом в Python?

интерфейс, для объекта-это набор методов и атрибутов для этого объекта.

в Python, мы можем использовать абстрактный базовый класс для определения и реализации интерфейса.

использование абстрактного базового класса

например, скажем, мы хотим использовать один из абстрактных базовых классов из collections модуль:

import collections
class MySet(collections.Set):
    pass

если мы попробуйте использовать его, мы получаем TypeError потому что класс, который мы создали, не поддерживает ожидаемое поведение устанавливает:

>>> MySet()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MySet with abstract methods
__contains__, __iter__, __len__

поэтому мы обязаны реализовать в по крайней мере__contains__,__iter__ и __len__. Давайте используем этот пример реализации из документация:

class ListBasedSet(collections.Set):
    """Alternate set implementation favoring space over speed
    and not requiring the set elements to be hashable. 
    """
    def __init__(self, iterable):
        self.elements = lst = []
        for value in iterable:
            if value not in lst:
                lst.append(value)
    def __iter__(self):
        return iter(self.elements)
    def __contains__(self, value):
        return value in self.elements
    def __len__(self):
        return len(self.elements)

s1 = ListBasedSet('abcdef')
s2 = ListBasedSet('defghi')
overlap = s1 & s2

реализация: создание абстрактного базового класса

мы можем создать наш собственный абстрактный базовый класс, установив метакласс к abc.ABCMeta и используя abc.abstractmethod декоратор по соответствующим методам. Метакласс будет добавить украшенные функции в __abstractmethods__ атрибут, предотвращающий создание экземпляров до тех пор, пока они не будут определены.

import abc

например, "effable" определяется как нечто, что может быть выражено словами. Скажем, мы хотели определить абстрактный базовый класс, который является эффективным, в Python 2:

class Effable(object):
    __metaclass__ = abc.ABCMeta
    @abc.abstractmethod
    def __str__(self):
        raise NotImplementedError('users must define __str__ to use this base class')

или в Python 3, с небольшим изменением в объявлении метакласса:

class Effable(object, metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def __str__(self):
        raise NotImplementedError('users must define __str__ to use this base class')

теперь, если мы попробуйте создать эффектный объект без реализации интерфейса:

class MyEffable(Effable): 
    pass

и попытайтесь создать его экземпляр:

>>> MyEffable()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MyEffable with abstract methods __str__

нам говорят, что мы еще не закончили работу.

теперь, если мы соблюдаем, предоставляя ожидаемый интерфейс:

class MyEffable(Effable): 
    def __str__(self):
        return 'expressable!'

тогда мы можем использовать конкретную версию класса, производную от абстрактной:

>>> me = MyEffable()
>>> print(me)
expressable!

есть и другие вещи, которые мы могли бы сделать с этим, как регистрация virtual подклассы, которые уже реализуют эти интерфейсы, но я думаю, что это выходит за рамки данного вопроса. Другие методы, продемонстрированные здесь, должны были бы адаптировать этот метод, используя abc модуль для этого, однако.

вывод

мы показали, что создание абстрактного базового класса определяет интерфейсы для пользовательских объектов в Python.

в Python >= 2.6 имеет Абстрактные Базовые Классы.

абстрактные базовые классы (сокращенно Азбука) дополняют утку-набрав по предоставление способа определения интерфейсов когда другие методы, такие как hasattr() было бы неуклюже. Языка Python поставляется с многие встроенные Азбуки для структур данных (в модуле коллекции), номера (в модуле числа), и потоки (в модуле ввода-вывода). Вы можете создать ваша собственная Азбука с азбукой модуль.

есть еще Интерфейс Zope модуль, который используется проектами за пределами zope, например twisted. Я не очень знаком с ним, но есть вики-страница здесь что может помочь.

В общем, вам не нужна концепция абстрактных классов или интерфейсов в python (отредактировано - см. ответ S. Lott для деталей).

Python на самом деле не имеет ни одного понятия.

Он использует duck typing, который удалил необходимость в интерфейсах (по крайней мере, для компьютера :-))

Python

Python >= 2.6: Абстрактные базовые классы do (http://docs.python.org/library/abc.html). и позволяют указать методы это должно быть реализовано в подклассах. Мне не очень нравится синтаксис, но функция есть. Большую часть времени, вероятно, лучше использовать утиный ввод с "использования" клиентской стороны.

в более простой способ объяснить: Интерфейс похож на пустую кастрюлю для кексов. Это файл класса с набором определений методов, которые не имеют кода.

абстрактный класс-это то же самое, но не все функции должны быть пустыми. Некоторые могут иметь код. Он не совсем пустой.

зачем дифференцировать: В Python нет большой практической разницы, но на уровне планирования для большого проекта можно было бы чаще говорить об интерфейсах, так как есть никакой код. Особенно если вы работаете с Java-программистами, которые привыкли к этому термину.

В общем случае интерфейсы используются только в языках, использующих модель класса с одним наследованием. В этих языках с одним наследованием интерфейсы обычно используются, если какой-либо класс может использовать определенный метод или набор методов. Кроме того, в этих языках с одним наследованием абстрактные классы используются либо для определения переменных класса в дополнение к ни одному или нескольким методам, либо для использования модели с одним наследованием для ограничения диапазона классов, которые могут использовать набор методов.

языки, которые поддерживают модель множественного наследования, как правило, используют только классы или абстрактные базовые классы, а не интерфейсы. Поскольку Python поддерживает множественное наследование, он не использует интерфейсы и вы хотели бы использовать базовые классы и абстрактные базовые классы.

http://docs.python.org/library/abc.html

Comments

    Ничего не найдено.