Python之装饰器学习

以下为在学习装饰器时的一些代码:

# 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) + ""
        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
## hello world

## 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) + ""
        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: hello, Hao Chen


## 用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()


你可能感兴趣的:(Python)