File tree Expand file tree Collapse file tree 2 files changed +105
-3
lines changed Expand file tree Collapse file tree 2 files changed +105
-3
lines changed Original file line number Diff line number Diff line change
1
+ #!/usr/bin/env python
2
+ # -*- encoding: utf-8 -*-
3
+ """
4
+ Topic: 解除包装器
5
+ Desc :
6
+ """
7
+
8
+ from functools import wraps
9
+
10
+ def decorator1 (func ):
11
+ @wraps (func )
12
+ def wrapper (* args , ** kwargs ):
13
+ print ('Decorator 1' )
14
+ return func (* args , ** kwargs )
15
+ return wrapper
16
+
17
+ def decorator2 (func ):
18
+ @wraps (func )
19
+ def wrapper (* args , ** kwargs ):
20
+ print ('Decorator 2' )
21
+ return func (* args , ** kwargs )
22
+ return wrapper
23
+
24
+ @decorator1
25
+ @decorator2
26
+ def add (x , y ):
27
+ return x + y
28
+
29
+ add (1 , 2 )
30
+ print ('-----------------' )
31
+ print (add .__wrapped__ (2 , 3 ))
Original file line number Diff line number Diff line change 5
5
----------
6
6
问题
7
7
----------
8
- todo...
8
+ 一个装饰器已经作用在一个函数上,你想撤销它,直接访问原始的未包装的那个函数。
9
+
10
+ |
9
11
10
12
----------
11
13
解决方案
12
14
----------
13
- todo...
15
+ 假设装饰器是通过 ``@wraps `` (参考9.2小节)来实现的,那么你可以通过访问 ``__wrapped__ `` 属性来访问原始函数:
16
+
17
+ .. code-block :: python
18
+
19
+ >> > @ somedecorator
20
+ >> > def add (x , y ):
21
+ ... return x + y
22
+ ...
23
+ >> > orig_add = add.__wrapped__
24
+ >> > orig_add(3 , 4 )
25
+ 7
26
+ >> >
27
+
28
+ |
14
29
15
30
----------
16
31
讨论
17
32
----------
18
- todo...
33
+ 直接访问未包装的原始函数在调试、内省和其他函数操作时是很有用的。
34
+ 但是我们这里的方案仅仅适用于在包装器中正确使用了 ``@wraps `` 或者直接设置了 ``__wrapped__ `` 属性的情况。
35
+
36
+ 如果有多个包装器,那么访问 ``__wrapped__ `` 属性的行为是不可预知的,应该避免这样做。
37
+ 在Python3.3中,它会略过所有的包装层,比如,假如你有如下的代码:
38
+
39
+ .. code-block :: python
40
+
41
+ from functools import wraps
42
+
43
+ def decorator1 (func ):
44
+ @wraps (func)
45
+ def wrapper (* args , ** kwargs ):
46
+ print (' Decorator 1' )
47
+ return func(* args, ** kwargs)
48
+ return wrapper
49
+
50
+ def decorator2 (func ):
51
+ @wraps (func)
52
+ def wrapper (* args , ** kwargs ):
53
+ print (' Decorator 2' )
54
+ return func(* args, ** kwargs)
55
+ return wrapper
56
+
57
+ @decorator1
58
+ @decorator2
59
+ def add (x , y ):
60
+ return x + y
61
+
62
+ 下面我们在Python3.3下测试:
63
+
64
+ .. code-block :: python
65
+
66
+ >> > add(2 , 3 )
67
+ Decorator 1
68
+ Decorator 2
69
+ 5
70
+ >> > add.__wrapped__ (2 , 3 )
71
+ 5
72
+ >> >
73
+
74
+ 下面我们在Python3.4下测试:
75
+
76
+ .. code-block :: python
77
+
78
+ >> > add(2 , 3 )
79
+ Decorator 1
80
+ Decorator 2
81
+ 5
82
+ >> > add.__wrapped__ (2 , 3 )
83
+ Decorator 2
84
+ 5
85
+ >> >
86
+
87
+ 最后要说的是,并不是所有的装饰器都使用了 ``@wraps `` ,因此这里的方案并不全部适用。
88
+ 特别的,内置的装饰器 ``@staticmethod `` 和 ``@classmethod `` 就没有遵循这个约定
89
+ (它们把原始函数存储在属性 ``__func__ `` 中)。
You can’t perform that action at this time.
0 commit comments