-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdecorators.py
More file actions
130 lines (91 loc) · 2.39 KB
/
decorators.py
File metadata and controls
130 lines (91 loc) · 2.39 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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
from functools import wraps, partial
z = 10
def log(f, x, y):
print(f.__name__, x, y)
return f(x, y) # 'f' is some object implementing __call__ method taking arg x and y
def log_dec(f):
def log(x, y):
rv = f(x, y)
print(f.__name__, x, y, '->', rv)
return rv
return log
def add(x, y=10):
''' Add two integers '''
return x + y
@log_dec
def add_with_dec(x, y=10):
''' Add two integers '''
return x + y
# python -i decorators.py [Interact with all the things script has created]
# >>> z
# 10
# >>> add [add is an object]
# <function add at 0x10b194230>
# >>> add.__code__
# <code object add at 0x10e55a3b0, file "decorators.py", line 4>
# >>> add.__defaults__
# (10,)
# >>> add.__doc__
# ' Add two integers '
# >>> add.__name__
# 'add'
sub = add
# >>> sub
# <function add at 0x10b194230>
# >>> sub.__code__
# <code object add at 0x10e55a3b0, file "decorators.py", line 4>
# >>> sub.__defaults__
# (10,)
# >>> sub.__doc__
# ' Add two integers '
# >>> sub.__name__
# 'add'
add.__call__(2, 3)
# 5
log(add, 10, 20)
# ('add', 10, 20)
# 30
# Logging multiple add statement requires 'log' to be called everytime
print('1+2=', log(add, 1, 2))
print('10+2=', log(add, 10, 2))
add = log_dec(add)
print('1+2=', add(1, 2))
print('10+2=', add(10, 2))
print('add_with_dec', add_with_dec(2, 3))
def debug(func):
@wraps(func) # Copies metadata(documentation,name) from 'func' to 'wrapper'
def wrapper(*args, **kwargs):
print(func.__qualname__)
return func(*args, **kwargs)
return wrapper
def add(a, b):
return a + b
func = debug(add)
func(4, 5)
# Decorators with args
def debug(func=None, *, prefix=''):
if func is None:
return partial(debug, prefix=prefix)
msg = prefix + func.__qualname__
@wraps(func) # Copies metadata(documentation,name) from 'func' to 'wrapper'
def wrapper(*args, **kwargs):
print(msg)
return func(*args, **kwargs)
return wrapper
def add(a, b):
return a + b
func = debug(prefix='****')(add)
func(4, 5)
# Class decorator , doesn't work with class and static methods
def debugmethods(cls):
for name, val in vars(cls).items():
if callable(val): # identify callables i.e methods
setattr(cls, name, debug(val))
return cls
@debugmethods
class Spam:
def a(self):
pass
def b(self):
pass
Spam().a()