Что такое версия Python для «Код против интерфейса, а не объекта»?

Вдохновленный большим вопросом (и множеством отличных ответов) отсюда.

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

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

  • Является ли внедрение абстрактного метода неписаным?
  • Создание сценария Python Объектно-ориентированный
  • Наследование методов docstrings в Python
  • Какова цель внутренних классов питона?
  • Как продлить форму регистрации «Django»?
  • Плохая практика для запуска кода в конструкторе, который, вероятно, потерпит неудачу?
  • Как сделать атрибут класса исключительным для суперкласса
  • Автоматическая регистрация методов класса с использованием декоратора
  • 4 Solutions collect form web for “Что такое версия Python для «Код против интерфейса, а не объекта»?”

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

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

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

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

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

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

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

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

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

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

    Например (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 .

    Это ява. Теперь вот что вы делаете в 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 является строковым типом и, следовательно, не нужного вам типа, он также автоматически запускается, и вы поймете (надеюсь).

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

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

    Что такое версия Python для «Код для интерфейса, а не для объекта»?

    Правильная цитата – « программа против интерфейса, а не реализация ». Принцип аналогичен принципу Python, который он сделал в Smalltalk, языке, на котором он возник.

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

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

    Interesting Posts
    Python - лучший язык программирования в мире.