Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 6e4c490

Browse files
committed
闭包,装饰器
1 parent a1bba1c commit 6e4c490

File tree

6 files changed

+261
-0
lines changed

6 files changed

+261
-0
lines changed

‎07-closure-deco/average.py‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# -*- coding: utf-8 -*-
2+
3+
4+
class Averager:
5+
6+
def __init__(self):
7+
self.series = []
8+
9+
def __call__(self, new_value):
10+
self.series.append(new_value)
11+
total = sum(self.series)
12+
return total / len(self.series)
13+
14+
15+
def make_averager_v1():
16+
series = []
17+
18+
def averager(new_value):
19+
series.append(new_value)
20+
total = sum(series)
21+
return total / len(series)
22+
return averager
23+
24+
25+
def make_averager_v2():
26+
count = 0
27+
total = 0
28+
29+
def averager(new_value):
30+
nonlocal count, total
31+
count += 1
32+
total += new_value
33+
return total / count
34+
return averager

‎07-closure-deco/clockdeco.py‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import time
4+
import functools
5+
6+
7+
def clock1(func):
8+
"""hello"""
9+
def clocked(*args):
10+
"""world"""
11+
t0 = time.time()
12+
result = func(*args)
13+
elapsed = time.time() - t0
14+
name = func.__name__
15+
arg_str = ', '.join(repr(arg) for arg in args)
16+
print('[%0.8fs] %s(%s) -> %r' % (elapsed, name, arg_str, result))
17+
return result
18+
return clocked
19+
20+
21+
# 改进的版本
22+
def clock(func):
23+
@functools.wraps(func)
24+
def clocked(*args, **kwargs):
25+
t0 = time.time()
26+
result = func(*args, **kwargs)
27+
elapsed = time.time() - t0
28+
name = func.__name__
29+
arg_lst = []
30+
if args:
31+
arg_lst.append(', '.join(repr(arg) for arg in args))
32+
if kwargs:
33+
pairs = ['%s=%r' % (k, w) for k, w in sorted(kwargs.items())]
34+
arg_lst.append(', '.join(pairs))
35+
arg_str = ', '.join(arg_lst)
36+
print('[%0.8fs] %s(%s) -> %r' % (elapsed, name, arg_str, result))
37+
return result
38+
return clocked
39+
40+
41+
@clock
42+
def snooze(seconds):
43+
time.sleep(seconds)
44+
45+
46+
@clock
47+
def factorial(n):
48+
"""计算n的阶乘"""
49+
return 1 if n < 2 else n * factorial(n - 1)
50+
51+
52+
if __name__ == '__main__':
53+
print('*' * 40, 'Calling snooze(.123)')
54+
snooze(.123)
55+
print('*' * 40, 'Calling factorial(6)')
56+
print('6! =', factorial(6))
57+
print(factorial.__name__)
58+
print(factorial.__doc__)

‎07-closure-deco/fibo.py‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import functools
4+
from clockdeco import clock
5+
6+
7+
@clock
8+
def fibonacci_slow(n):
9+
if n < 2:
10+
return n
11+
return fibonacci_slow(n - 2) + fibonacci_slow(n - 1)
12+
13+
14+
# 使用缓存,速度更快
15+
@functools.lru_cache()
16+
@clock
17+
def fibonacci(n):
18+
if n < 2:
19+
return n
20+
return fibonacci(n - 2) + fibonacci(n - 1)
21+
22+
23+
24+
if __name__ == '__main__':
25+
print(fibonacci(10))

‎07-closure-deco/generic.py‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from functools import singledispatch
4+
from collections import abc
5+
import numbers
6+
import html
7+
8+
9+
@singledispatch
10+
def htmlize(obj):
11+
content = html.escape(repr(obj))
12+
return f'<pre>{content}</pre>'
13+
14+
15+
@htmlize.register(str)
16+
def _(text):
17+
content = html.escape(text).replace('\n', '<br>\n')
18+
return f'<p>{content}</p>'
19+
20+
21+
@htmlize.register(numbers.Integral)
22+
def _(n):
23+
return f'<pre>{n} (0x{n:x})</pre>'
24+
25+
26+
@htmlize.register(tuple)
27+
@htmlize.register(abc.MutableSequence)
28+
def _(seq):
29+
inner = '</li>\n<li>'.join(htmlize(item) for item in seq)
30+
return '<ul>\n<li>' + inner + '</li>\n</ul>'

‎07-closure-deco/registration.py‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# -*- coding: utf-8 -*-
2+
3+
registry = []
4+
5+
6+
def register(func):
7+
print('running register(%s)' % func)
8+
registry.append(func)
9+
return func
10+
11+
12+
@register
13+
def f1():
14+
print('running f1()')
15+
16+
17+
@register
18+
def f2():
19+
print('running f2()')
20+
21+
22+
def f3():
23+
print('running f3()')
24+
25+
26+
def main():
27+
print('running main()')
28+
print('registry ->', registry)
29+
f1()
30+
f2()
31+
f3()
32+
33+
34+
if __name__ == '__main__':
35+
main()

‎07-closure-deco/strategy.py‎

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from collections import namedtuple
4+
5+
Customer = namedtuple('Customer', 'name fidelity')
6+
7+
8+
class LineItem:
9+
10+
def __init__(self, product, quantity, price):
11+
self.product = product
12+
self.quantity = quantity
13+
self.price = price
14+
15+
def total(self):
16+
return self.price * self.quantity
17+
18+
19+
class Order:
20+
21+
def __init__(self, customer, cart, promotion=None):
22+
self.customer = customer
23+
self.cart = list(cart)
24+
self.promotion = promotion
25+
26+
def total(self):
27+
if not hasattr(self, '__total'):
28+
self.__total = sum(item.total() for item in self.cart)
29+
return self.__total
30+
31+
def due(self):
32+
if self.promotion is None:
33+
discount = 0
34+
else:
35+
discount = self.promotion(self)
36+
return self.total() - discount
37+
38+
def __repr__(self):
39+
fmt = '<Order total: {:.2f} due: {:.2f}>'
40+
return fmt.format(self.total(), self.due())
41+
42+
43+
# best promotion version 4
44+
promos = []
45+
46+
47+
def promotion(promo_func):
48+
promos.append(promo_func)
49+
return promo_func
50+
51+
52+
@promotion
53+
def fidelity_promo(order):
54+
"""5% discount for customers with 1000 or more fidelity points"""
55+
return order.total() * 0.05 if order.customer.fidelity >= 1000 else 0
56+
57+
58+
@promotion
59+
def bulk_item_promo(order):
60+
"""10% discount for each LineItem with 20 or more units"""
61+
discount = 0
62+
for item in order.cart:
63+
if item.quantity >= 20:
64+
discount += item.total() * 0.1
65+
return discount
66+
67+
68+
@promotion
69+
def large_order_promo(order):
70+
"""7% discount for orders with 10 or more distinct items"""
71+
distinct_items = {item.product for item in order.cart}
72+
if len(distinct_items) >= 10:
73+
return order.total() * 0.07
74+
return 0
75+
76+
77+
def best_promo(order):
78+
"""Select best discount available"""
79+
return max(promo(order) for promo in promos)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /