Уведомления

Группа в Telegram: @pythonsu

#1 Фев. 10, 2011 16:15:36

Subideal Ox
От:
Зарегистрирован: 2010-11-23
Сообщения: 65
Репутация: +  0  -
Профиль   Отправить e-mail  

Программные интерфейсы в Python.

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

В любом случае, за производительность должен отвечать компилятор или интерпретатор, а не синтаксис языка.



Офлайн

#2 Фев. 10, 2011 19:27:13

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

Программные интерфейсы в Python.

в чем прикол 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())

Отредактировано (Фев. 10, 2011 19:28:12)

Офлайн

#3 Фев. 10, 2011 19:44:23

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Программные интерфейсы в Python.

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` приводит их мозг к расплавленному состоянию!



Офлайн

#4 Фев. 12, 2011 20:35:40

Isem
От:
Зарегистрирован: 2010-08-27
Сообщения: 447
Репутация: +  7  -
Профиль   Отправить e-mail  

Программные интерфейсы в Python.

Краткость - сестра таланта.
М.В.Ломоносов.

з.ы. Не надо мне говорить, что это не Ломоносов.



Офлайн

#5 Фев. 15, 2011 09:43:31

Subideal Ox
От:
Зарегистрирован: 2010-11-23
Сообщения: 65
Репутация: +  0  -
Профиль   Отправить e-mail  

Программные интерфейсы в Python.

Isem
Краткость - сестра таланта.
   М.В.Ломоносов.

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

ps Привет Чехову ;)



Офлайн

#6 Фев. 15, 2011 11:34:32

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Программные интерфейсы в Python.

Subideal Ox
Точность все-таки гораздо более сестра :D
А краткость и скорость выполнения уже потом
И было у таланта три сестры и не одного брата :)



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Офлайн

#7 Фев. 18, 2011 18:48:21

Isem
От:
Зарегистрирован: 2010-08-27
Сообщения: 447
Репутация: +  7  -
Профиль   Отправить e-mail  

Программные интерфейсы в Python.

Subideal Ox
ps Привет Чехову
И все-таки Ломоносов жил раньше :)



Офлайн

#8 Фев. 18, 2011 18:52:12

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Программные интерфейсы в Python.

И при чем здесь программные интерфейсы?



Офлайн

#9 Фев. 18, 2011 18:57:47

Isem
От:
Зарегистрирован: 2010-08-27
Сообщения: 447
Репутация: +  7  -
Профиль   Отправить e-mail  

Программные интерфейсы в Python.

Это история, без знания которой будущее туманно, но без крайностей.



Офлайн

#10 Март 22, 2013 20:32:38

krishnarama
Зарегистрирован: 2013-02-27
Сообщения: 51
Репутация: +  -36  -
Профиль   Отправить e-mail  

Программные интерфейсы в Python.

Андрей Светлов
Утиная типизация при всех ее достоинствах не заменяет понятие “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__

Отредактировано krishnarama (Март 22, 2013 20:33:44)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version