Skip to content

Commit 3077efa

Browse files
committed
更新md
更新md
1 parent 3cb96db commit 3077efa

File tree

3 files changed

+202
-5
lines changed

3 files changed

+202
-5
lines changed

python_advance/装饰器.md

Lines changed: 186 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
**装饰器:本质上是一个Python函数(嵌套函数),他可以让其他函数在不做任何代码变动的情况下增加额外的功能,装饰器的返回值也是一个函数对象。有了装饰器,可以抽离出大量与函数功能本身无关的代码并重复使用。需求场景如:插入日志、性能测试、权限校验等。**
1+
**装饰器:本质上是一个Python函数(嵌套函数),它的参数是另一个函数(被装饰函数),他可以让其他函数在不做任何代码变动的情况下增加额外的功能,装饰器的返回值也是一个函数对象。有了装饰器,可以抽离出大量与函数功能本身无关的代码并重复使用。需求场景如:插入日志、性能测试、权限校验等。**
22

3-
#### 最简单的装饰器
3+
#### 1.最简单的装饰器
44
被装饰函数没有参数:
55

66
```python
@@ -20,7 +20,7 @@ if __name__ == '__main__':
2020
# func_a 耗时: 3.0008597373962402
2121
func_a()
2222
```
23-
#### 被装饰函数带参数
23+
#### 2.被装饰函数带参数
2424
可变参数+关键字参数可以表示所有的参数情况。
2525

2626
```python
@@ -42,7 +42,7 @@ if __name__ == '__main__':
4242
# func_a 耗时: 2.0003809928894043
4343
func_a(2)
4444
```
45-
#### 带参数的装饰器
45+
#### 3.带参数的装饰器
4646
实现一个装饰器,控制被装饰函数的执行次数。三层嵌套。
4747

4848
```python
@@ -64,3 +64,185 @@ if __name__ == '__main__':
6464
# foo执行第3次
6565
foo()
6666
```
67+
68+
#### 4.装饰器有一个关键的特性是,它们在被装饰的函数定义之后立即运行。这通常是在导入时(即 Python 加载模块时)
69+
```python
70+
registry = []
71+
72+
73+
def register(func):
74+
print('running register({})'.format(func))
75+
registry.append(func)
76+
return func
77+
78+
79+
@register
80+
def f1():
81+
print('running f1()')
82+
83+
84+
def f2():
85+
print('running f2()')
86+
87+
88+
if __name__ == '__main__':
89+
print(registry)
90+
print('running main')
91+
f1()
92+
f2()
93+
```
94+
95+
运行结果
96+
```python
97+
running register(<function f1 at 0x000002341B186620>)
98+
[<function f1 at 0x000002341B186620>]
99+
running main
100+
running f1()
101+
running f2()
102+
```
103+
104+
#### 5.标准库中的装饰器 functools.lru_cache()
105+
functools.lru_cache是非常实用的装饰器,它实现了备忘功能。这是一项优化技术,它把耗时的函数的结果保存
106+
起来,避免传入相同的参数时重复计算。
107+
* 参数maxsize:指定缓存的最大结果数量
108+
109+
**不使用functools.lru_cache的情况**
110+
111+
```python
112+
import time
113+
114+
def count_time(func):
115+
def count(*args, **kwargs):
116+
start = time.time()
117+
res = func(*args, **kwargs)
118+
end = time.time()
119+
print('执行函数{}({})耗时: {}'.format(func.__name__, args[0], end - start))
120+
return res
121+
return count
122+
123+
@count_time
124+
def fibonacci(n):
125+
if n < 2:
126+
return n
127+
return fibonacci(n-1) + fibonacci(n-1)
128+
129+
if __name__ == '__main__':
130+
fibonacci(5)
131+
```
132+
运行结果,发现同一个值计算了多次
133+
```python
134+
执行函数fibonacci(1)耗时: 0.0
135+
执行函数fibonacci(1)耗时: 0.0
136+
执行函数fibonacci(2)耗时: 0.0
137+
执行函数fibonacci(1)耗时: 0.0
138+
执行函数fibonacci(1)耗时: 0.0
139+
执行函数fibonacci(2)耗时: 0.0
140+
执行函数fibonacci(3)耗时: 0.0
141+
执行函数fibonacci(1)耗时: 0.0
142+
执行函数fibonacci(1)耗时: 0.0
143+
执行函数fibonacci(2)耗时: 0.0
144+
执行函数fibonacci(1)耗时: 0.0
145+
执行函数fibonacci(1)耗时: 0.0
146+
执行函数fibonacci(2)耗时: 0.0
147+
执行函数fibonacci(3)耗时: 0.0
148+
执行函数fibonacci(4)耗时: 0.0
149+
执行函数fibonacci(1)耗时: 0.0
150+
执行函数fibonacci(1)耗时: 0.0
151+
执行函数fibonacci(2)耗时: 0.0
152+
执行函数fibonacci(1)耗时: 0.0
153+
执行函数fibonacci(1)耗时: 0.0
154+
执行函数fibonacci(2)耗时: 0.0
155+
执行函数fibonacci(3)耗时: 0.0
156+
执行函数fibonacci(1)耗时: 0.0
157+
执行函数fibonacci(1)耗时: 0.0
158+
执行函数fibonacci(2)耗时: 0.0
159+
执行函数fibonacci(1)耗时: 0.0
160+
执行函数fibonacci(1)耗时: 0.0
161+
执行函数fibonacci(2)耗时: 0.0
162+
执行函数fibonacci(3)耗时: 0.0
163+
执行函数fibonacci(4)耗时: 0.0
164+
执行函数fibonacci(5)耗时: 0.0
165+
```
166+
167+
**使用functools.lru_cache的情况**
168+
```python
169+
import time
170+
import functools
171+
172+
def count_time(func):
173+
def count(*args, **kwargs):
174+
start = time.time()
175+
res = func(*args, **kwargs)
176+
end = time.time()
177+
print('执行函数{}({})耗时: {}'.format(func.__name__, args[0], end - start))
178+
return res
179+
return count
180+
181+
@functools.lru_cache()
182+
@count_time
183+
def fibonacci(n):
184+
if n < 2:
185+
return n
186+
return fibonacci(n-1) + fibonacci(n-1)
187+
188+
if __name__ == '__main__':
189+
fibonacci(5)
190+
```
191+
192+
结果,避免了重复计算
193+
```python
194+
执行函数fibonacci(1)耗时: 0.0
195+
执行函数fibonacci(2)耗时: 0.0
196+
执行函数fibonacci(3)耗时: 0.0
197+
执行函数fibonacci(4)耗时: 0.0
198+
执行函数fibonacci(5)耗时: 0.0
199+
```
200+
201+
#### 6.标准库中的装饰器 functools.singledispatch
202+
203+
Python3.4新增的 functools.singledispatch 装饰器可以把整体方案拆分成多个模块,甚至可以为你无法修改的类提供专门的函数。使用@singledispatch 装饰的普通函数会变成泛函数(generic function):根据第一个参数的类型,以不同方式执行相同操作的一组函数.
204+
205+
```python
206+
import functools
207+
import html
208+
import numbers
209+
from collections import abc
210+
211+
212+
@functools.singledispatch
213+
def htmlize(obj):
214+
content = html.escape(repr(obj))
215+
return '<pre>{}</pre>'.format(content)
216+
217+
218+
@htmlize.register(str)
219+
def _(text):
220+
content = html.escape(text).replace('\n', '</br>\n')
221+
return '<pre>{}</pre>'.format(content)
222+
223+
224+
@htmlize.register(numbers.Integral)
225+
def _(n):
226+
return '<pre>{}({})</pre>'.format(n, hex(n))
227+
228+
229+
@htmlize.register(tuple)
230+
@htmlize.register(abc.MutableSequence)
231+
def _(seq):
232+
inner = '</li>\n<li>'.join(htmlize(item) for item in seq)
233+
return '<ul>\n<li>' + inner + '</li>\n</ul>'
234+
235+
if __name__ == '__main__':
236+
print(htmlize(17))
237+
print(htmlize(['alpha', 66, {3, 2, 1}]))
238+
```
239+
240+
结果
241+
```python
242+
<pre>17(0x11)</pre>
243+
<ul>
244+
<li><pre>alpha</pre></li>
245+
<li><pre>66(0x42)</pre></li>
246+
<li><pre>{1, 2, 3}</pre></li>
247+
</ul>
248+
```

python_basic/main.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@
1919
17. [json文件处理](json文件处理.md)
2020
18. [Excel文件处理](Excel文件处理.md)
2121
19. [深拷贝与浅拷贝](深拷贝与浅拷贝.md)
22-
20. [列表推导式,map,filter,reduce](列表推导式.md)
22+
20. [列表推导式,字典推导式,生成器表达式,map,filter,reduce](列表推导式.md)

python_basic/列表推导式.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,18 @@ from functools import reduce
3737
sum_ = reduce((lambda x, y:x+y), list_x)
3838
print(sum_) # 36
3939
```
40+
41+
#### 生成器表达式
42+
与列表推导式不同的是,生成器表达式逐个产出元素,不会一次产生出所有的结果。这样可以避免额外的内存占用。
43+
```python
44+
for item in (x*2 for x in list_x):
45+
print(item)
46+
```
47+
48+
#### 字典推导式
49+
```python
50+
data = [('China', '86'), ('USA', '1'), ('XXX', '87')]
51+
data_dict = {country: areacode for country, areacode in data}
52+
# {'China': '86', 'USA': '1', 'XXX': '87'}
53+
print(data_dict)
54+
```

0 commit comments

Comments
 (0)