Se ha denunciado esta presentación.
Se está descargando tu SlideShare. ×

Decorators' recipes

Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio

Eche un vistazo a continuación

1 de 27 Anuncio

Más Contenido Relacionado

Presentaciones para usted (20)

A los espectadores también les gustó (19)

Anuncio

Similares a Decorators' recipes (20)

Anuncio

Más reciente (20)

Decorators' recipes

  1. 1. Рецепты декораторов Юрий Юревич yury.yurevich@equelli.com | http://pyobject.ru PyCamp Kyiv, Киев, 2010. 1
  2. 2. О докладчике ● Живу от Киева >2000 км ● В области разработки ПО >7 лет ● С Python >5 лет ● Блог о Python >3 лет ● Конференция по Ruby&Python >2 лет 2
  3. 3. О докладе ● Ингредиенты ● Функция — объект первого рода ● Декоратор — обёртка ● Синтаксический сахар ● Рецепты ● Инфраструктура ● Интерфейс ● Адаптер ● Гард ● Примеры из реальной жизни 3
  4. 4. Ингредиенты 4
  5. 5. Ингредиенты (2) Декоратор = функции(объекты первого рода) + вложенные функции + @синтаксический_сахар 5
  6. 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. 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. 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. 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. 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. 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. 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
  13. 13. Рецепты 13
  14. 14. Декоратор — «вынесение общего знаменателя за скобки» По сути, пересмотр паттернов ООП для Python и реализация средствами декораторов. 14
  15. 15. Инфраструктура 15
  16. 16. Инфраструктура ● Изменяет окружение ● Не меняет функцию/аргументы (обычно) ● Примеры: ● @commit ● @cache ● Псевдокод >>> def infrastructure(func): ... def wrapper(*args, **kwargs): ... prepare_environ() ... res = func(*args, **kwargs) ... fix_environ() ... return res ... return wrapper 16
  17. 17. Интерфейс 17
  18. 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
  19. 19. Адаптер 19
  20. 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. Гард 21
  22. 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. 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. 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. 25. Кунг-фу Это к Сергею Щетинину ;) http://self.maluke.com/ 25
  26. 26. P.S. Ссылки ● http://www.siafoo.net/article/68 ● http://pypi.python.org/pypi/decorator ● http://tinyurl.com/decorator-guard 26
  27. 27. Спасибо за внимание Вопросы? 27

×