Форум сайта python.su
0
regallУ меня ощущение, что отсутствие множественного наследования в Java это какой-то trade-off связанный с оптимизацией скорости работы, а не c конфликтом имен. Ведь и в С++ множественное наследование рекомендуют делать не слишком множественным именно из-за проблем с производительностью. Возможно, дело в раннем связывании. Но это уже за пределами моей компетенции :( И за пределами круга моих интересов :D
Единственное, что могу добавить, что Java всегда борется с повышением быстродействия и т.д. и зачастую архитектурные решения Java принимаются под давлением потребностей повышения скорости выполнения.
Офлайн
32
в чем прикол 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)
Офлайн
14
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` приводит их мозг к расплавленному состоянию!
Офлайн
7
Краткость - сестра таланта.
М.В.Ломоносов.
з.ы. Не надо мне говорить, что это не Ломоносов.
Офлайн
0
IsemТочность все-таки гораздо более сестра :D
Краткость - сестра таланта.
М.В.Ломоносов.
з.ы. Не надо мне говорить, что это не Ломоносов.
Офлайн
72
Subideal OxИ было у таланта три сестры и не одного брата :)
Точность все-таки гораздо более сестра :D
А краткость и скорость выполнения уже потом
Офлайн
7
Subideal OxИ все-таки Ломоносов жил раньше :)
ps Привет Чехову
Офлайн
14
И при чем здесь программные интерфейсы?
Офлайн
7
Это история, без знания которой будущее туманно, но без крайностей.
Офлайн
-36
Андрей СветловЕсть люди, которые Вам не поверят.
Утиная типизация при всех ее достоинствах не заменяет понятие “public interface”.

>>> 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)
Офлайн