以下为在学习装饰器时的一些代码:
# coding:utf-8
import time
import functools
def log_cost_time(func):
@functools.wraps(func)
def wrapped(*args,**kwargs):
begin = time.time()
try:
return func(*args,**kwargs)
finally:
print('func %s cost %s' % (func.__name__, time.time() - begin))
return wrapped
# complex_func = log_cost_time(complex_func)
@log_cost_time
def complex_func(num):
ret = 0
for i in range(num):
ret += i * i
return ret
if __name__ == '__main__':
print(complex_func(100000))
print(complex_func.__name__)
##################################################################
def log_cost_time(stream):
def inner_dec(func):
def wrapped(*args, **kwargs):
import time
begin = time.time()
try:
return func(*args, **kwargs)
finally:
stream.write('func %s cost %s \n' % (func.__name__, time.time() - begin))
return wrapped
return inner_dec
import sys
@log_cost_time(sys.stdout)
def complex_func(num):
ret = 0
for i in range(num):
ret += i * i
return ret
if __name__ == '__main__':
print(complex_func(100000))
###########################################################
# coding:utf-8
import time
import functools
import sys
def log_cost_time(stream):
def inner_dec(func): # 装饰器带参数
@functools.wraps(func)
def wrapped(*args,**kwargs):
begin = time.time()
try:
return func(*args,**kwargs)
finally:
stream.write('func %s cost %s\n'
% (func.__name__, time.time() - begin))
return wrapped
return inner_dec
# complex_func = log_cost_time(complex_func)(*args,**kwargs)
@log_cost_time(sys.stdout)
def complex_func(num):
ret = 0
for i in range(num):
ret += i * i
return ret
if __name__ == '__main__':
print(complex_func(100000))
print(complex_func.__name__)
#############################################################
## 装饰器对类的修饰
def Haha(clz):
clz.__str__ = lambda s:"Haha"
return clz
@Haha
class Widget(object):
'''class Widget'''
if __name__ == "__main__":
w = Widget()
print(w)
################################################################
import functools
def catchall(func):
@functools.wraps(func)
def wrapped(*args,**kwargs):
try:
return func(*args,**kwargs)
except:
pass
return wrapped
@catchall
def f():
for i in range(10):
print(i)
if __name__ == '__main__':
f()
################################################################
## 参考文章地址:
## https://www.python.org/dev/peps/pep-0318/#syntax-alternatives
## PYTHON修饰器的函数式编程:http://coolshell.cn/articles/11265.html
####============PYTHON修饰器的函数式编程=======================
## Hello World
def hello(fn):
def wrapper():
print("hello, %s" % fn.__name__)
fn()
print("goodby, %s" % fn.__name__)
return wrapper
@hello
def foo():
print("i am foo")
foo()
## Decorator 的本质
def fuck(fn):
print("fuck %s" % fn.__name__[::-1].upper()) # fn.__name__[::-1] 字符串倒序输出
@fuck
def wfg():
pass
## 多个装饰器
# func = decorator_one(decorator_two(func))
@decorator_one
@decorator_two
def func():
pass
## 带参数及多个Decrorator
def makeHtmlTag(tag, *args, **kwds):
def real_decorator(fn):
css_class = "class = '{0}'".format(kwds["css_class"]) \
if "css_class" in kwds else ""
def wrapped(*args, **kwds):
return "<" + tag + css_class + ">" + \
fn(*args, **kwds) + "</" + tag + ">"
return wrapped
return real_decorator
@makeHtmlTag(tag="b",css_class="bold_css")
@makeHtmlTag(tag="i",css_class="italic_css")
def hello():
return "hello world"
print(hello())
## result
## <bclass = 'bold_css'><iclass = 'italic_css'>hello world</i></b>
## class式的 Decorator
class myDecorator(object):
def __init__(self,fn):
print("inside myDecorator.__init__()")
self.fn = fn
def __call__(self):
self.fn()
print("inside myDecorator.__call__()")
@myDecorator
def aFunction():
print("inside aFunction()")
print("Finished decorating aFunction()")
aFunction()
# 输出:
# inside myDecorator.__init__()
# Finished decorating aFunction()
# inside aFunction()
# inside myDecorator.__call__()
'''
上面这个示例展示了,用类的方式声明一个decorator。我们可以看到这个类中有两个成员:
1)一个是__init__(),这个方法是在我们给某个函数decorator时被调用,所以,需要有一个fn的参数,也就是被decorator的函数。
2)一个是__call__(),这个方法是在我们调用被decorator函数时被调用的。
上面输出可以看到整个程序的执行顺序
'''
## HTML.PY
class makeHtmlTagClass(object):
def __init__(self, tag, css_class=""):
self._tag = tag
self._css_class = " class='{}' ".format(css_class)\
if css_class != "" else ""
def __call__(self, fn):
def wrapped(*args, **kwargs):
return "<" + self._tag + self._css_class + ">" \
+ fn(*args, **kwargs) + "</" + self._tag + ">"
return wrapped
@makeHtmlTagClass(tag="b",css_class="bold_css")
@makeHtmlTagClass(tag="i",css_class="italic_css")
def hello(name):
return "hello, {}".format(name)
print(hello("Hao Chen"))
# result: <b class='bold_css' ><i class='italic_css' >hello, Hao Chen</i></b>
## 用Decorator设置函数的调用参数
## 你有三种方法可以干这个事:
## 第一种,通过 **kwargs,这种方法decorator会在kwargs中注入参数。
def decorate_A(function):
def wrap_function(*args, **kwargs):
kwargs['str'] = 'Hello!'
return function(*args, **kwargs)
return wrap_function
@decorate_A
def print_message_A(*args, **kwargs):
print(kwargs['str'])
print_message_A()
## 第二种,约定好参数,直接修改参数
def decorate_B(function):
def wrap_function(*args, **kwargs):
str = 'Hello!'
return function(str, *args, **kwargs)
return wrap_function
@decorate_B
def print_message_B(str, *args, **kwargs):
print(str)
print_message_B()
## 第三种,通过 *args 注入
def decorate_C(function):
def wrap_function(*args, **kwargs):
str = 'Hello!'
#args.insert(1, str)
args = args +(str,)
return function(*args, **kwargs)
return wrap_function
class Printer:
@decorate_C
def print_message(self, str, *args, **kwargs):
print(str)
p = Printer()
p.print_message()
## Decorator的副作用
## 输出的是“wrapper”,而不是我们期望的“foo”,这会给我们的程序埋一些坑。所以,Python的functool包中提供了一个叫wrap的decorator来消除这样的副作用
from functools import wraps
def hello(fn):
@wraps(fn)
def wrapper():
print("hello, %s" % fn.__name__)
fn()
print("goodby, %s" % fn.__name__)
return wrapper
@hello
def foo():
'''foo help doc'''
print("i am foo")
pass
foo()
print(foo.__name__) # 输出 foo
print(foo.__doc__) # 输出 foo help doc
## 给函数调用做缓存
from functools import wraps
def memo(fn):
cache = {}
miss = object()
@wraps(fn)
def wrapper(*args):
result = cache.get(args,miss)
if result is miss:
result = fn(*args)
cache[args] = result
return result
return wrapper
@memo
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(10))
## 用decorator,在调用函数前查询一下缓存,如果没有才调用了,有了就从缓存中返回值。
# 一下子,这个递归从二叉树式的递归成了线性的递归。
## 注册回调函数
class MyApp():
def __init__(self):
self.func_map = {}
def register(self, name):
def func_wrapper(func):
self.func_map[name] = func
return func
return func_wrapper
def call_method(self, name=None):
func = self.func_map.get(name,None)
if func is None:
raise Exception("No function registered against - " + str(name))
return func()
app = MyApp()
@app.register('/')
def main_page_func():
return "This is the main page."
@app.register('/next_page')
def next_page_func():
return "This is the next page."
print(app.call_method('/'))
print(app.call_method('/next_page'))
# 输出:This is the main page.
# This is the next page.
## 给函数打日志
from functools import wraps
import time
def logger(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
ts = time.time()
result = fn(*args, **kwargs)
te = time.time()
print("function = {0}".format(fn.__name__))
print(" arguments = {0} {1}".format(args, kwargs))
print(" return = {0}".format(result))
print(" time = {0}".format(te - ts))
return result
return wrapper
@logger
def multipy(x, y):
return x * y
@logger
def sum_num(n):
s = 0
for i in range(n+1):
s += i
return s
print("multipy is %d" % multipy(2,10))
print("sum is %d" % sum_num(100))
print("sum is %d" % sum_num(10000000))
## 线程异步
from threading import Thread
from functools import wraps
from time import sleep
def async(func):
@wraps(func)
def async_func(*args, **kwargs):
func_hl = Thread(target=func, args=args, kwargs=kwargs)
func_hl.start()
return func_hl
return async_func
if __name__ == '__main__':
@async
def print_somedata():
print('starting print_somedata')
sleep(2)
print('print_somedata: 2 sec passed')
sleep(2)
print('print_somedata: 2 sec passed')
sleep(2)
print('finished print_somedata')
def main():
print_somedata()
print('back in main')
print_somedata()
print('back in main')
main()