-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdecorator.py
More file actions
71 lines (56 loc) · 3.15 KB
/
decorator.py
File metadata and controls
71 lines (56 loc) · 3.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# -*- coding: utf-8 -*-
#-------------------------------------------------------------------------------
# Copyright (c) 2015 Artur Eganyan
#
# This work is provided "AS IS", WITHOUT ANY WARRANTY, express or implied.
#-------------------------------------------------------------------------------
# Декоратор - это функция, которая принимает один объект и возвращает вместо
# него другой. Обычно декоратор создает для исходного объекта обертку, которая
# как-то меняет его поведение, и возвращает эту обертку.
# Этот декоратор принимает функцию и возвращает обертку над ней, которая
# приводит результат функции к unicode
def unicode_version(func):
def wrapper(*args):
return unicode(func(*args), 'utf8')
return wrapper
# Создаем функцию и применяем к ней декоратор
def f():
return "Это строка в кодировке utf8"
f = unicode_version(f)
# Ровно то же самое можно сделать инструкцией @<декоратор>
@unicode_version
def f():
return "Это строка в кодировке utf8"
# Теперь f будет оберткой над исходной функцией, возвращающей unicode
# (правда, будут делаться три вызова вместо двух: wrapper -> unicode -> f)
print f()
# Инструкцию @<декоратор> можно размещать только перед описанием функции
# или класса (def ... и class ...). Можно размещать несколько инструкций
# подряд.
def some_decorator(func):
func.some_arg = u"Тут был декоратор"
return func
@some_decorator
@unicode_version
def f():
return "Test"
# Декораторы будут вызваны в обратном порядке
f = some_decorator(unicode_version(f))
# В декоратор можно передавать параметры: @<декоратор>(<параметры>). Они будут
# переданы декоратору вместо функции/класса. Такой декоратор должен вернуть
# другой декоратор, принимающий функцию/класс, и уже он будет вызван следом
# за исходным декоратором.
# Это декоратор, принимающий параметр, который должен быть числом, и
# возвращающий один из ранее созданных декораторов
def funny_decorator(arg):
if arg > 0:
return unicode_version
else:
return some_decorator
@funny_decorator(-1)
def f():
pass
# Для такого декоратора будет выполнен следующий код
d = funny_decorator(-1)
f = d(f)
print f.some_arg # Будет выведен результат работы some_decorator