Найти - Пользователи
Полная версия: Программные интерфейсы в Python.
Начало » Python для новичков » Программные интерфейсы в Python.
1 2 3 4
Subideal Ox
regall
Единственное, что могу добавить, что Java всегда борется с повышением быстродействия и т.д. и зачастую архитектурные решения Java принимаются под давлением потребностей повышения скорости выполнения.
У меня ощущение, что отсутствие множественного наследования в Java это какой-то trade-off связанный с оптимизацией скорости работы, а не c конфликтом имен. Ведь и в С++ множественное наследование рекомендуют делать не слишком множественным именно из-за проблем с производительностью. Возможно, дело в раннем связывании. Но это уже за пределами моей компетенции :( И за пределами круга моих интересов :D

В любом случае, за производительность должен отвечать компилятор или интерпретатор, а не синтаксис языка.
o7412369815963
в чем прикол zope.interface? ABC в отличие от зопы проверяет наличие методов на стадии создания экземпляра.
import zope.interface

class IVehicle(zope.interface.Interface):
"""Any moving thing"""
speed = zope.interface.Attribute("""Movement speed""")
def move():
"""Make a single step"""

class Car(object):
zope.interface.implements(IVehicle)

assert IVehicle.implementedBy(Car)
assert IVehicle.providedBy(Car())
Андрей Светлов
zope.interface служит хорошей документацией.
Я всегда изучаю модуль с описанием интерфейсов, если он есть.

“Прикол” неплохо рассмотрен в human.ru.txt из пакета. Приведу его весь.
——————————
Использование реестра адаптеров
===============================

Данный документ содержит небольшую демонстрацию пакета ``zope.interface`` и его
реестра адаптеров. Документ рассчитывался как конкретный, но более узкий пример
того как использовать интерфейсы и адаптеры вне Zope 3.

Сначала нам необходимо импортировать пакет для работы с интерфейсами.

>>> import zope.interface

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

>>> class IFile(zope.interface.Interface):

… body = zope.interface.Attribute(u'Содержимое файла.')


Для статистики нам часто необходимо знать размер файла. Но было бы несколько
топорно релизовывать определение размера прямо для объекта файла, т.к. размер
больше относится к мета-данным. Таким образом мы создаем еще один интерфейс для
представления размера какого-либо объекта.

>>> class ISize(zope.interface.Interface):

… def getSize():
… ‘Return the size of an object.’


Теперь мы должны создать класс реализующий наш файл. Необходимо что бы наш
объект хранил информацию о том, что он реализует интерфейс `IFile`. Мы также
создаем атрибут с содержимым файла по умолчанию (для упрощения нашего примера).

>>> class File(object):

… zope.interface.implements(IFile)
… body = ‘foo bar’


Дальше мы создаем адаптер, который будет предоставлять интерфейс `ISize`
получая любой объект предоставляющий интерфейс `IFile`. По соглашению мы
используем атрибут `__used_for__` для указания интерфейса который как мы
ожидаем предоставляет адаптируемый объект, `IFile` в нашем случае. На самом
деле этот атрибут используется только для документирования. В случае если
адаптер используется для нескольких интерфейсов можно указать их все в виде
кортежа.

Опять же по соглашению конструктор адаптера получает один аргумент - context
(контекст). В нашем случае контекст - это экземпляр `IFile` (объект,
предоставляющий `IFile`) который используется для получения из него размера.
Так же по соглашению контекст сохраняется а адаптере в атрибуте с именем
`context`. Twisted комьюнити ссылается на контекст как на объект `original`.
Таким образом можно также дать аргументу любое подходящее имя, например `file`.

>>> class FileSize(object):

… zope.interface.implements(ISize)
… __used_for__ = IFile

… def __init__(self, context):
… self.context = context

… def getSize(self):
… return len(self.context.body)


Теперь когда мы написали наш адаптер мы должны зарегистрировать его в реестре
адаптеров, что бы его можно было запросить когда он понадобится. Здесь нет
какого-либо глобального реестра адаптеров, таким образом мы должны
самостоятельно создать для нашего примера реестр.

>>> from zope.interface.adapter import AdapterRegistry
>>> registry = AdapterRegistry()

Реестр содержит отображение того, что адаптер реализует на основе другого
интерфейса который предоставляет объект. Поэтому дальше мы регистрируем адаптер
который адаптирует интерфейс `IFile` к интерфейсу `ISize`. Первый аргумент к
методу `register()` реестра - это список адаптируемых интерфейсов. В нашем
случае мы имеем только один адаптируемый интерфейс - `IFile`. Список
интерфейсов имеет смысл для использования концепции мульти-адаптеров, которые
требуют нескольких оригинальных объектов для адаптации к новому интерфейсу. В
этой ситуации конструктор адаптера будет требовать новый аргумент для каждого
оригинального интерфейса.

Второй аргумент метода `register()` - это интерфейс который предоставляет
адаптер, в нашем случае `ISize`. Третий аргумент - имя адаптера. Сейчас нам не
важно имя адаптера и мы передаем его как пустую строку. Обычно имена полезны
если используются адаптеры для одинакового набора интерфейсов, но в различных
ситуациях. Последний аргумент - это класс адаптера.

>>> registry.register(, ISize, ‘', FileSize)

Теперь мы можем использовать реестр для запроса адаптера.

>>> registry.lookup1(IFile, ISize, ’')
<class ‘__main__.FileSize’>

Попробуем более практичный пример. Создадим экземпляр `File` и создадим адаптер
использующий запрос реестра. Затем мы увидим возвращает ли адаптер корректный
размер при вызове `getSize()`.

>>> file = File()
>>> size = registry.lookup1(IFile, ISize, ‘')(file)
>>> size.getSize()
7

На самом деле это не очень практично, т.к. нам нужно самим передавать все
аргументы методу запроса. Существует некоторый “синтаксический лединец” который
позволяет нам получить экземпляр адаптера просто вызвав `ISize(file)`. Что бы
использовать эту функциональность нам понадобится добавить наш реестр к списку
adapter_hooks, который находится в модуле с адаптерами. Этот список хранит
коллекцию вызываемых объектов которые вызываются автоматически когда вызывается
IFoo(obj); их предназначение - найти адаптеры которые реализуют интерфейс
для определенного экземпляра контекста.

Необходимо реализовать свою собственную функцию для поиска адаптера; данный
пример описывает одну из простейших функций для использования с реестром, но
также можно реализовать поисковые функции которые, например, используют
кэширование, или адаптеры сохраняемые в базе. Функция поиска должна принимать
желаемый на выходе интерфейс (в нашем случае `ISize`) как первый аргумент и
контекст для адаптации (`file`) как второй. Функция должна вернуть адаптер,
т.е. экзмепляр `FileSize`.

>>> def hook(provided, object):
… adapter = registry.lookup1(zope.interface.providedBy(object),
… provided, ’')
… return adapter(object)


Теперь мы просто добавляем нашу функцию к списку `adapter_hooks`.

>>> from zope.interface.interface import adapter_hooks
>>> adapter_hooks.append(hook)

Как только функция зарегистрирована мы можем использовать желаемый синтаксис.

>>> size = ISize(file)
>>> size.getSize()
7

После нам нужно прибраться за собой, что бы другие получили чистый список
`adaper_hooks` после нас.

>>> adapter_hooks.remove(hook)

Это все. Здесь намеренно отложена дискуссия об именованных и мульти-адаптерах,
т.к. данный текст рассчитан как практическое и простое введение в интерфейсы и
адаптеры Zope 3. Для более подробной информации имеет смысл прочитать
`adapter.txt` из пакета `zope.interface`, что бы получить более формальное,
справочное и полное трактование пакета. Внимание: многие жаловались, что
`adapter.txt` приводит их мозг к расплавленному состоянию!
Isem
Краткость - сестра таланта.
М.В.Ломоносов.

з.ы. Не надо мне говорить, что это не Ломоносов.
Subideal Ox
Isem
Краткость - сестра таланта.
   М.В.Ломоносов.

з.ы.  Не надо мне говорить, что это не Ломоносов.
Точность все-таки гораздо более сестра :D
А краткость и скорость выполнения уже потом

ps Привет Чехову ;)
PooH
Subideal Ox
Точность все-таки гораздо более сестра :D
А краткость и скорость выполнения уже потом
И было у таланта три сестры и не одного брата :)
Isem
Subideal Ox
ps Привет Чехову
И все-таки Ломоносов жил раньше :)
Андрей Светлов
И при чем здесь программные интерфейсы?
Isem
Это история, без знания которой будущее туманно, но без крайностей.
krishnarama
Андрей Светлов
Утиная типизация при всех ее достоинствах не заменяет понятие “public interface”.
Есть люди, которые Вам не поверят.

Сколько лет должно было пройти, пока фитон дошел до явовских фишек - юникодных строк по дефолту, интерфейсов?

Интерфейсы нужны, во-первых, для документации (догадаться, что Element из lxml.etree притворяется списком можно, только сравнив список методов, которые, конечно же, надо помнить наизусть), во-вторых, для ограничений (если требовать просто последовательность, то можно вместо списка получить строку).

А почему не работает такой код:

>>> class A(collections.Sized):
… pass

>>> A.__len__ = lambda: 1
>>> A
<class ‘__main__.A’>
>>> A.__len__
<unbound method A.<lambda>>
>>> A()
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
TypeError: Can't instantiate abstract class A with abstract methods __len__
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB