SlideShare uma empresa Scribd logo
1 de 27
Baixar para ler offline
Рецепты
декораторов
Юрий Юревич yury.yurevich@equelli.com | http://pyobject.ru

                PyCamp Kyiv, Киев, 2010.



                                                             1
О докладчике
●   Живу от Киева >2000 км
●   В области разработки ПО >7 лет
●   С Python >5 лет
●   Блог о Python >3 лет
●   Конференция по Ruby&Python >2 лет




                                        2
О докладе
●   Ингредиенты
    ●   Функция — объект первого рода
    ●   Декоратор — обёртка
    ●   Синтаксический сахар
●   Рецепты
    ●   Инфраструктура
    ●   Интерфейс
    ●   Адаптер
    ●   Гард
●   Примеры из реальной жизни
                                        3
Ингредиенты




              4
Ингредиенты (2)

Декоратор =
функции(объекты первого рода)
+ вложенные функции +
@синтаксический_сахар



                                5
Функция — объект первого рода
>>> def give_me_twice(x):
...     return x*2
...
>>> function
<function give_me_twice at 0xb76278b4>

>>> def call_it(func, arg)
...     return func(arg)
...

>>> def make_strange(func)
...     replaced = lambda x: func(x + 5)
...     return replaced
...

>>> strange_twice = make_strange(give_me_twice)




                                                  6
Декоратор — обёртка функции
>>> def give_me_twice(x):
...     return x*2
...

>>> def make_strange(func)
...     replaced = lambda x: func(x + 5)
...     return replaced
...

>>> give_me_twice = make_strange(give_me_twice)

                                       декоратор




                                                   7
Вложенные функции
>>> def give_me_twice(x):
...     return x*2
...

>>> def make_really_strange(func):
...     def wrapper(z):
...         res = func(z + 2)
...         return res
...     return wrapper
...

>>> give_me_twice = make_really_strange(give_me_twice)
>>> give_me_twice
<function wrapper at 0xb7570924>




                                                         8
Фабрика!
>>> def give_me_twice(x):
...     return x*2
...

>>> def make_really_omg(num):
...     def decor(func):
...         def wrapper(z):
...             res = func(z + num)
...             return res
...         return wrapper
...    return decor
...

>>> decorator = make_really_omg(5)
>>> decorator
<function decor at 0xb7570336>
>>> give_me_twice = decorator(give_me_twice)
>>> give_me_twice
<function wrapper at 0xb7570823>
                                               9
Еще и классы
>>> def make_really_strange(func):       func → wrapper
...     def wrapper(z):
...         res = func(z + 2)
...         return res
...     return wrapper



>>> class make_really_strange(object):   func → <instance>
...    def __init__(self, func):
...        self.func = func
...    def __call__(self, z):
...        res = self.func(z + 2)
...        return res




                                                          10
Синтаксический сахар
  @name — неявный вызов name(func)
«Обычный»
>>> def give_me_twice(x):
...     return x*2
...

>>> give_me_twice = make_really_omg(5)(give_me_twice)



«Подслащенный»
>>> @make_really_omg(5)
... def give_me_twice(x):
...     return x*2
...

                                                        11
Дайте два!
●   «снизу вверх»
●   «изнутри наружу»
●   Не очень красиво
@usecase
@render_to('usecase_research.html')
@usecase_provider
@rules.apply_(default_rules)
def research_unit(request):
   ...



usecase(render_to('usecase_research.html')
(usecase_provider(rules.apply_(default_rules)
(research_unit))))
                                                12
Рецепты




          13
Декоратор —
  «вынесение общего
знаменателя за скобки»

   По сути, пересмотр паттернов ООП для Python
      и реализация средствами декораторов.




                                                 14
Инфраструктура




                 15
Инфраструктура
●   Изменяет окружение
●   Не меняет функцию/аргументы (обычно)
●   Примеры:
    ●   @commit
    ●   @cache
●   Псевдокод
     >>> def infrastructure(func):
     ...     def wrapper(*args, **kwargs):
     ...         prepare_environ()
     ...         res = func(*args, **kwargs)
     ...         fix_environ()
     ...         return res
     ...     return wrapper                    16
Интерфейс




            17
Интерфейс
●   Регистрация однородных объектов
●   Проверка требований (опционально)
●   Примеры:
    ●   @register.tag (Django)
●   Псевдокод
     >>> CALLBACKS = []
     >>> def callback(func):
     ...     def wrapper(*args, **kwargs):
     ...         res = func(*args, **kwargs)
     ...         assert res is not None
     ...         return res
     ...     CALLBACKS.append(wrapper)
     ...     return wrapper                    18
Адаптер




          19
Адаптер
●   Согласование API, преобразование данных
●   Часто — фабрики
●   Примеры:
    ●   @render_to (Django, Александр Соловьев)
    ●   @permalink (Django)
●   Псевдокод
        >>> def render_to(template):
        ...     def decor(view):
        ...         def wrapper(request, *args, **kwargs):
        ...             context = view(request, *args, **kwargs)
        ...             return render(template, request, context)
        ...         return wrapper
        ...     return decor
                                                                    20
Гард




       21
Гард
●   Вынос типичного условного перехода
●   Примеры:
    ●   @login_required (Django)
    ●   @validate (Pylons)
●   Псевдокод
     >>> def login_required(view):
     ...     def wrapper(request, *args, **kwargs):
     ...         if request.user.is_authenticated():
     ...             return view(request, *args, **kwargs)
     ...         else:
     ...             return HttpResponseForbidden()
     ...     return wrapper
                                                             22
Реальная жизнь - ajax_request
def ajax_request(func):
    def wrapper(request, *args, **kwargs):        гард
        if request.method == 'POST':
            response = func(request, *args, **kwargs)
        else:
            response = {
                'error': {
                    'type': 405,
                    'message': 'Accepts POST only'
                }
            }                                                адаптер
        if isinstance(response, dict):
            resp = JsonResponse(response)
            if 'error' in response:
                resp.status_code = response['error'].get('type', 500)
            return resp
        return response
    return functools.wraps(func)(wrapper)

                                               http://is.gd/7h6H7   23
Реальная жизнь - reg.simple_tag
def simple_tag(self, func):
    params, xx, xxx, defaults = getargspec(func)

   class SimpleNode(Node):
       [...]
                                                     адаптер
   compile_func = curry(
       generic_tag_compiler,
       params,
       defaults,
       getattr(func, "_decorated_function", func).__name__,
       SimpleNode
   )
   compile_func.__doc__ = func.__doc__
                                                  интерфейс
   self.tag(
       getattr(func, "_decorated_function", func).__name__,
       compile_func
   )
   return func
                                           http://is.gd/7hdMu   24
Кунг-фу



   Это к Сергею Щетинину ;)

   http://self.maluke.com/




                             25
P.S. Ссылки
●   http://www.siafoo.net/article/68
●   http://pypi.python.org/pypi/decorator
●   http://tinyurl.com/decorator-guard




                                            26
Спасибо за внимание




Вопросы?
                      27

Mais conteúdo relacionado

Mais procurados

AddConf. Дмитрий Сошников - Будущее ECMAScript
AddConf. Дмитрий Сошников  - Будущее ECMAScriptAddConf. Дмитрий Сошников  - Будущее ECMAScript
AddConf. Дмитрий Сошников - Будущее ECMAScript
Dmitry Soshnikov
 
Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"
Python Meetup
 
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf Conference
 

Mais procurados (20)

AddConf. Дмитрий Сошников - Будущее ECMAScript
AddConf. Дмитрий Сошников  - Будущее ECMAScriptAddConf. Дмитрий Сошников  - Будущее ECMAScript
AddConf. Дмитрий Сошников - Будущее ECMAScript
 
Красота и изящность стандартной библиотеки Python
Красота и изящность стандартной библиотеки PythonКрасота и изящность стандартной библиотеки Python
Красота и изящность стандартной библиотеки Python
 
Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.
 
Лекция 2. Всё, что вы хотели знать о функциях в Python.
Лекция 2. Всё, что вы хотели знать о функциях в Python.Лекция 2. Всё, что вы хотели знать о функциях в Python.
Лекция 2. Всё, что вы хотели знать о функциях в Python.
 
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1
 
Javascript
JavascriptJavascript
Javascript
 
Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.
 
Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.
 
Профилирование и отладка Django
Профилирование и отладка DjangoПрофилирование и отладка Django
Профилирование и отладка Django
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стиль
 
Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"
 
Объектное и прототипное программирование в Javascript
Объектное и прототипное программирование в JavascriptОбъектное и прототипное программирование в Javascript
Объектное и прототипное программирование в Javascript
 
Лекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GILЛекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GIL
 
Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.
 
Поговорим о JavaScript, основы и современные тенденции развития языка
Поговорим о JavaScript, основы и современные тенденции развития языкаПоговорим о JavaScript, основы и современные тенденции развития языка
Поговорим о JavaScript, основы и современные тенденции развития языка
 
Лекция 4. Строки, байты, файлы и ввод/вывод.
 Лекция 4. Строки, байты, файлы и ввод/вывод. Лекция 4. Строки, байты, файлы и ввод/вывод.
Лекция 4. Строки, байты, файлы и ввод/вывод.
 
Лекция 8. Итераторы, генераторы и модуль itertools.
 Лекция 8. Итераторы, генераторы и модуль itertools. Лекция 8. Итераторы, генераторы и модуль itertools.
Лекция 8. Итераторы, генераторы и модуль itertools.
 
Haskell - huge presentation for DevDay about Haskell language
Haskell - huge presentation for DevDay about Haskell languageHaskell - huge presentation for DevDay about Haskell language
Haskell - huge presentation for DevDay about Haskell language
 
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
 

Destaque

Qualificação (Curta) Julho 2009
Qualificação (Curta) Julho 2009Qualificação (Curta) Julho 2009
Qualificação (Curta) Julho 2009
Rodrigo Senra
 
Sabadell PPT CASTELLA
Sabadell PPT CASTELLASabadell PPT CASTELLA
Sabadell PPT CASTELLA
SARISTA
 
American Necrospecialists--the modern artisans of death
American Necrospecialists--the modern artisans of deathAmerican Necrospecialists--the modern artisans of death
American Necrospecialists--the modern artisans of death
Ingrid Fernandez, PhD
 

Destaque (19)

김인수 - 인터넷 포털기업에서 디자인하기
김인수 - 인터넷 포털기업에서 디자인하기김인수 - 인터넷 포털기업에서 디자인하기
김인수 - 인터넷 포털기업에서 디자인하기
 
Qualificação (Curta) Julho 2009
Qualificação (Curta) Julho 2009Qualificação (Curta) Julho 2009
Qualificação (Curta) Julho 2009
 
Circuitos
CircuitosCircuitos
Circuitos
 
#MWC15Health Peter Chau China Connected Health Alliance
#MWC15Health Peter Chau China Connected Health Alliance#MWC15Health Peter Chau China Connected Health Alliance
#MWC15Health Peter Chau China Connected Health Alliance
 
Sabadell PPT CASTELLA
Sabadell PPT CASTELLASabadell PPT CASTELLA
Sabadell PPT CASTELLA
 
Alphabet
AlphabetAlphabet
Alphabet
 
U.S. History Ch. !2
U.S. History Ch. !2U.S. History Ch. !2
U.S. History Ch. !2
 
Startup Lessons In A Tweet.
Startup Lessons In A Tweet.Startup Lessons In A Tweet.
Startup Lessons In A Tweet.
 
OrgCultureView_v0.1
OrgCultureView_v0.1OrgCultureView_v0.1
OrgCultureView_v0.1
 
ПУМБ 2015-2016
ПУМБ 2015-2016ПУМБ 2015-2016
ПУМБ 2015-2016
 
Arte egipcio
Arte egipcioArte egipcio
Arte egipcio
 
FEL 12 Release Notes
FEL 12 Release NotesFEL 12 Release Notes
FEL 12 Release Notes
 
JetStor NAS 724UX and 724UX 10G ZFS appliance
JetStor NAS 724UX and 724UX 10G ZFS applianceJetStor NAS 724UX and 724UX 10G ZFS appliance
JetStor NAS 724UX and 724UX 10G ZFS appliance
 
Aa
AaAa
Aa
 
Wikiconference 2016 talk Burgstaller
Wikiconference 2016 talk BurgstallerWikiconference 2016 talk Burgstaller
Wikiconference 2016 talk Burgstaller
 
Ep2: How Sales can Ride the Social Media Wave
Ep2: How Sales can Ride the Social Media WaveEp2: How Sales can Ride the Social Media Wave
Ep2: How Sales can Ride the Social Media Wave
 
Bubbl us-3
Bubbl us-3Bubbl us-3
Bubbl us-3
 
American Necrospecialists--the modern artisans of death
American Necrospecialists--the modern artisans of deathAmerican Necrospecialists--the modern artisans of death
American Necrospecialists--the modern artisans of death
 
CV
CVCV
CV
 

Semelhante a Decorators' recipes

Web осень 2013 лекция 8
Web осень 2013 лекция 8Web осень 2013 лекция 8
Web осень 2013 лекция 8
Technopark
 
Характерные черты функциональных языков программирования
Характерные черты функциональных языков программированияХарактерные черты функциональных языков программирования
Характерные черты функциональных языков программирования
Alex.Kolonitsky
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
Technopark
 
Hacking PostgreSQL. Обзор исходного кода
Hacking PostgreSQL. Обзор исходного кодаHacking PostgreSQL. Обзор исходного кода
Hacking PostgreSQL. Обзор исходного кода
Anastasia Lubennikova
 
Михаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияМихаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знания
Yandex
 
GAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камниGAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камни
Yehor Nazarkin
 
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to UsZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf Conference
 

Semelhante a Decorators' recipes (20)

Основы Python. Функции
Основы Python. ФункцииОсновы Python. Функции
Основы Python. Функции
 
Web осень 2013 лекция 8
Web осень 2013 лекция 8Web осень 2013 лекция 8
Web осень 2013 лекция 8
 
Scala on android
Scala on androidScala on android
Scala on android
 
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
 
Характерные черты функциональных языков программирования
Характерные черты функциональных языков программированияХарактерные черты функциональных языков программирования
Характерные черты функциональных языков программирования
 
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
 
Теории и практики фунционального программирования - GDG D2D
Теории и практики фунционального программирования - GDG D2DТеории и практики фунционального программирования - GDG D2D
Теории и практики фунционального программирования - GDG D2D
 
8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)
 
Charming python sc2-8
Charming python sc2-8Charming python sc2-8
Charming python sc2-8
 
Clojure #2 (2014)
Clojure #2 (2014)Clojure #2 (2014)
Clojure #2 (2014)
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
 
Hacking PostgreSQL. Обзор исходного кода
Hacking PostgreSQL. Обзор исходного кодаHacking PostgreSQL. Обзор исходного кода
Hacking PostgreSQL. Обзор исходного кода
 
Михаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияМихаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знания
 
GAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камниGAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камни
 
Михаил Давыдов - JavaScript. Базовые знания
Михаил Давыдов - JavaScript. Базовые знанияМихаил Давыдов - JavaScript. Базовые знания
Михаил Давыдов - JavaScript. Базовые знания
 
Михаил Давыдов - Транспорт, ajax
Михаил Давыдов - Транспорт, ajaxМихаил Давыдов - Транспорт, ajax
Михаил Давыдов - Транспорт, ajax
 
PHP7 - что ожидать?
PHP7 - что ожидать?PHP7 - что ожидать?
PHP7 - что ожидать?
 
Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?
 
Теории и практики функционального программирования.
Теории и практики функционального программирования.Теории и практики функционального программирования.
Теории и практики функционального программирования.
 
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to UsZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
 

Mais de Yury Yurevich

ekb.py: KISS REST API
ekb.py: KISS REST APIekb.py: KISS REST API
ekb.py: KISS REST API
Yury Yurevich
 
ekb.py: Mini Zen of Python
ekb.py: Mini Zen of Pythonekb.py: Mini Zen of Python
ekb.py: Mini Zen of Python
Yury Yurevich
 
Александр Гладыш — Visual editor for business logic in Lua and JS
Александр Гладыш — Visual editor for business logic in Lua and JSАлександр Гладыш — Visual editor for business logic in Lua and JS
Александр Гладыш — Visual editor for business logic in Lua and JS
Yury Yurevich
 

Mais de Yury Yurevich (12)

ekb.py: KISS REST API
ekb.py: KISS REST APIekb.py: KISS REST API
ekb.py: KISS REST API
 
ekb.py: Mini Zen of Python
ekb.py: Mini Zen of Pythonekb.py: Mini Zen of Python
ekb.py: Mini Zen of Python
 
PyCon UA 2011: Test Infected
PyCon UA 2011: Test InfectedPyCon UA 2011: Test Infected
PyCon UA 2011: Test Infected
 
Александр Гладыш — Visual editor for business logic in Lua and JS
Александр Гладыш — Visual editor for business logic in Lua and JSАлександр Гладыш — Visual editor for business logic in Lua and JS
Александр Гладыш — Visual editor for business logic in Lua and JS
 
Лев Валкин — Кое-что про Erlang
Лев Валкин — Кое-что про ErlangЛев Валкин — Кое-что про Erlang
Лев Валкин — Кое-что про Erlang
 
Ильшад Хабибуллин — BlueBream
Ильшад Хабибуллин — BlueBreamИльшад Хабибуллин — BlueBream
Ильшад Хабибуллин — BlueBream
 
Иван Иноземцев — Fantom
Иван Иноземцев — FantomИван Иноземцев — Fantom
Иван Иноземцев — Fantom
 
Александр Гладыш — Lua
Александр Гладыш — LuaАлександр Гладыш — Lua
Александр Гладыш — Lua
 
About Python
About PythonAbout Python
About Python
 
About (unit) testing
About (unit) testingAbout (unit) testing
About (unit) testing
 
SQLAlchemy Seminar
SQLAlchemy SeminarSQLAlchemy Seminar
SQLAlchemy Seminar
 
Almost Success Story: Unix to Linux migration
Almost Success Story: Unix to Linux migrationAlmost Success Story: Unix to Linux migration
Almost Success Story: Unix to Linux migration
 

Decorators' recipes

  • 2. О докладчике ● Живу от Киева >2000 км ● В области разработки ПО >7 лет ● С Python >5 лет ● Блог о Python >3 лет ● Конференция по Ruby&Python >2 лет 2
  • 3. О докладе ● Ингредиенты ● Функция — объект первого рода ● Декоратор — обёртка ● Синтаксический сахар ● Рецепты ● Инфраструктура ● Интерфейс ● Адаптер ● Гард ● Примеры из реальной жизни 3
  • 5. Ингредиенты (2) Декоратор = функции(объекты первого рода) + вложенные функции + @синтаксический_сахар 5
  • 6. Функция — объект первого рода >>> def give_me_twice(x): ... return x*2 ... >>> function <function give_me_twice at 0xb76278b4> >>> def call_it(func, arg) ... return func(arg) ... >>> def make_strange(func) ... replaced = lambda x: func(x + 5) ... return replaced ... >>> strange_twice = make_strange(give_me_twice) 6
  • 7. Декоратор — обёртка функции >>> def give_me_twice(x): ... return x*2 ... >>> def make_strange(func) ... replaced = lambda x: func(x + 5) ... return replaced ... >>> give_me_twice = make_strange(give_me_twice) декоратор 7
  • 8. Вложенные функции >>> def give_me_twice(x): ... return x*2 ... >>> def make_really_strange(func): ... def wrapper(z): ... res = func(z + 2) ... return res ... return wrapper ... >>> give_me_twice = make_really_strange(give_me_twice) >>> give_me_twice <function wrapper at 0xb7570924> 8
  • 9. Фабрика! >>> def give_me_twice(x): ... return x*2 ... >>> def make_really_omg(num): ... def decor(func): ... def wrapper(z): ... res = func(z + num) ... return res ... return wrapper ... return decor ... >>> decorator = make_really_omg(5) >>> decorator <function decor at 0xb7570336> >>> give_me_twice = decorator(give_me_twice) >>> give_me_twice <function wrapper at 0xb7570823> 9
  • 10. Еще и классы >>> def make_really_strange(func): func → wrapper ... def wrapper(z): ... res = func(z + 2) ... return res ... return wrapper >>> class make_really_strange(object): func → <instance> ... def __init__(self, func): ... self.func = func ... def __call__(self, z): ... res = self.func(z + 2) ... return res 10
  • 11. Синтаксический сахар @name — неявный вызов name(func) «Обычный» >>> def give_me_twice(x): ... return x*2 ... >>> give_me_twice = make_really_omg(5)(give_me_twice) «Подслащенный» >>> @make_really_omg(5) ... def give_me_twice(x): ... return x*2 ... 11
  • 12. Дайте два! ● «снизу вверх» ● «изнутри наружу» ● Не очень красиво @usecase @render_to('usecase_research.html') @usecase_provider @rules.apply_(default_rules) def research_unit(request): ... usecase(render_to('usecase_research.html') (usecase_provider(rules.apply_(default_rules) (research_unit)))) 12
  • 14. Декоратор — «вынесение общего знаменателя за скобки» По сути, пересмотр паттернов ООП для Python и реализация средствами декораторов. 14
  • 16. Инфраструктура ● Изменяет окружение ● Не меняет функцию/аргументы (обычно) ● Примеры: ● @commit ● @cache ● Псевдокод >>> def infrastructure(func): ... def wrapper(*args, **kwargs): ... prepare_environ() ... res = func(*args, **kwargs) ... fix_environ() ... return res ... return wrapper 16
  • 18. Интерфейс ● Регистрация однородных объектов ● Проверка требований (опционально) ● Примеры: ● @register.tag (Django) ● Псевдокод >>> CALLBACKS = [] >>> def callback(func): ... def wrapper(*args, **kwargs): ... res = func(*args, **kwargs) ... assert res is not None ... return res ... CALLBACKS.append(wrapper) ... return wrapper 18
  • 20. Адаптер ● Согласование API, преобразование данных ● Часто — фабрики ● Примеры: ● @render_to (Django, Александр Соловьев) ● @permalink (Django) ● Псевдокод >>> def render_to(template): ... def decor(view): ... def wrapper(request, *args, **kwargs): ... context = view(request, *args, **kwargs) ... return render(template, request, context) ... return wrapper ... return decor 20
  • 21. Гард 21
  • 22. Гард ● Вынос типичного условного перехода ● Примеры: ● @login_required (Django) ● @validate (Pylons) ● Псевдокод >>> def login_required(view): ... def wrapper(request, *args, **kwargs): ... if request.user.is_authenticated(): ... return view(request, *args, **kwargs) ... else: ... return HttpResponseForbidden() ... return wrapper 22
  • 23. Реальная жизнь - ajax_request def ajax_request(func): def wrapper(request, *args, **kwargs): гард if request.method == 'POST': response = func(request, *args, **kwargs) else: response = { 'error': { 'type': 405, 'message': 'Accepts POST only' } } адаптер if isinstance(response, dict): resp = JsonResponse(response) if 'error' in response: resp.status_code = response['error'].get('type', 500) return resp return response return functools.wraps(func)(wrapper) http://is.gd/7h6H7 23
  • 24. Реальная жизнь - reg.simple_tag def simple_tag(self, func): params, xx, xxx, defaults = getargspec(func) class SimpleNode(Node): [...] адаптер compile_func = curry( generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode ) compile_func.__doc__ = func.__doc__ интерфейс self.tag( getattr(func, "_decorated_function", func).__name__, compile_func ) return func http://is.gd/7hdMu 24
  • 25. Кунг-фу Это к Сергею Щетинину ;) http://self.maluke.com/ 25
  • 26. P.S. Ссылки ● http://www.siafoo.net/article/68 ● http://pypi.python.org/pypi/decorator ● http://tinyurl.com/decorator-guard 26