Что такое версия Python для «Код против интерфейса, а не объекта»? - PullRequest
42 голосов
/ 28 декабря 2010

Вдохновлен большим вопросом (и кучей отличных ответов) из здесь.

Имеет ли утверждение "Код против интерфейса, а не объект" какое-либо значение в Python?1005 *

Я ищу ответы, подобные тем, которые содержатся в Первоначальном вопросе , но с фрагментами и мыслями Python.

Ответы [ 4 ]

60 голосов
/ 28 декабря 2010

«Код против интерфейса, а не объекта» не имеет буквального смысла в Python, потому что язык не имеет функции интерфейса. Эквивалент грубый Python - это «использовать утку». Если вы хотите увидеть, является ли объект уткой, другими словами, вы должны проверить, есть ли у него метод quack(), или, что еще лучше, попытаться quack() и обеспечить соответствующую обработку ошибок, а не проверять, если он является экземпляром Duck.

Обычными типами уток в Python являются файлы (ну, на самом деле, файловые объекты), отображения (dict -подобные объекты), вызываемые объекты (функционально-подобные объекты), последовательности (list -подобные объекты) и итерируемые (вещи, которые вы можете перебирать, которые могут быть контейнерами или генераторами).

В качестве примера, функции Python, которым нужен файл, обычно будут рады принять объект, реализующий методы file, в которых он нуждается; он не должен быть производным от класса file. Например, чтобы использовать объект в качестве стандартного, главное, что ему понадобится, - это метод write() (и, возможно, flush() и close(), который на самом деле ничего не должен делать). Аналогично, вызываемый объект - это любой объект, имеющий метод __call__(); он не должен быть получен из типа функции (фактически, вы не можете получить из типа функции).

Вы должны принять аналогичный подход. Проверьте методы и атрибуты, которые вам нужны для того, что вы собираетесь делать с объектом. А еще лучше, документируйте то, что вы ожидаете, и предполагайте, что тот, кто вызывает ваш код, не является полной глупостью. (Если они дадут вам объект, который вы не можете использовать, они наверняка поймут это достаточно быстро из ошибок, которые они получают.) Проверяйте для определенных типов только при необходимости. иногда необходимо, поэтому Python дает вам type(), isinstance() и issubclass(), но будьте осторожны с ними.

Печатание уток в Python эквивалентно «коду против интерфейса, а не по объекту» в том смысле, что вам советуют не делать свой код слишком зависимым от типа объекта, а скорее видеть, имеет ли он нужный вам интерфейс , Разница в том, что в Python «интерфейс» означает неформальный набор атрибутов и методов объекта, которые обеспечивают определенное поведение, а не языковую конструкцию, специально названную interface.

Вы можете до некоторой степени формализовать Python-интерфейсы, используя модуль abc, который позволяет вам объявить, что данный класс является подклассом данного «абстрактного базового класса» (интерфейса), используя любые критерии, которые вы пожелаете, например, так как «он имеет атрибуты color, tail_length и quack, а quack может вызываться». Но это все же намного менее строго, чем статические языки, имеющие функцию интерфейса.

29 голосов
/ 28 декабря 2010

Чтобы понять интерфейсы в Python, вы должны понимать типизацию с утиным типом.Из самого Python глоссарий :

duck-typing : стиль программирования, который не смотрит на тип объекта, чтобы определить, имеет ли он правильный интерфейс;вместо этого метод или атрибут просто вызывается или используется («Если он выглядит как утка и крякает как утка, он должен быть уткой».) Уделяя особое внимание интерфейсам, а не конкретным типам, хорошо разработанный код повышает его гибкость, позволяяполиморфное замещение.Утиная типография избегает тестов с использованием type () или isinstance ().(Заметьте, однако, что типизацию утки можно дополнить абстрактными базовыми классами.) Вместо этого обычно используются тесты hasattr () или программирование EAFP.

Python поддерживает кодирование интерфейсов, только онипринудительно, но по соглашению.Такие понятия, как iterables, callables или файловый интерфейс, очень распространены в Python, а также встроенные функции, основанные на таких интерфейсах, как map, filter или Reduce.

18 голосов
/ 28 декабря 2010

Интерфейс означает, что вы ожидаете, что определенные методы будут присутствовать и стандартизированы по объектам; это точка интерфейса или абстрактного базового класса или любой другой реализации, которую вы хотите рассмотреть.

Например (Java), можно использовать интерфейс для симметричного шифрования, например:

public interface cipher 
{
    public void encrypt(byte[] block, byte[] key); 
    public void decrypt(byte[] block, byte[] key);    
}

Тогда вы можете реализовать это:

public class aes128 implements cipher
{ 
    public void encrypt(byte[] block, byte[] key)
    {
        //...
    }
    public void decrypt(byte[] block, byte[] key)
    {
        //...
    }
}

Затем можно объявить объект следующим образом:

cipher c;

Что мы здесь сделали? Итак, мы создали этот объект c, тип которого должен соответствовать типу интерфейса. c может относиться ко всему, что соответствует этому интерфейсу, поэтому следующим этапом будет:

c = new aes128();

Теперь вы можете вызывать методы, которые вы ожидаете иметь cipher.

Это Java. Теперь вот что вы делаете в python:

class aes128(Object):

    def __init__(self):
        pass

    def encrypt(self, block, key):
        # here I am going to pass, but you really 
        # should check what you were passed, it could be 
        # anything. Don't forget, if you're a frog not a duck
        # not to quack!
        pass

Если вы хотите использовать это, и вы не уверены, что объект, который вы прошли, просто попробуйте его использовать:

c = aes128()
try:
    c.encrypt(someinput, someoutput)
except:
    print "eh? No encryption method?!"

Здесь вы полагаетесь на реализацию c.encrypt в raise, если он не может обработать то, что было передано, если метод существует. Конечно, если c является строковым типом и, следовательно, не того типа, который вам требуется, он также сгенерирует автоматически, и вы поймаете (надеюсь).

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

Я надеюсь, что это показывает практическую разницу между ними.

0 голосов
/ 29 декабря 2010

Что такое версия Python для «Код против интерфейса, а не объекта»?*».Этот принцип действует в Python так же, как и в Smalltalk, на языке, на котором он возник.

Делает утверждение «Код для интерфейса, а не для объекта».иметь какое-либо значение в Python?

Да.Он имеет такое же значение в Python, как и в языке, с которого произошла эта цитата (Smalltalk), и в любом другом языке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...