Python_day_06_装饰器

装饰器: 器,函数;实质上是用来装饰函数的函数
产品经理和开发人员

1. 定义万能装饰器

def 装饰器名称(f):
    def wrapper(*args, **kwargs):
        # 函数执行之前的操作
        f(*args, **kwargs)
        # 函数执行之后的操作
    return wrapper

def 装饰器名称(f):
    def wrapper(*args, **kwargs):
        if 条件:
            f(*args, **kwargs)
        else:
            # 报错并抛出异常 raise Error("xxxxxx")
    return wrapper

2. 有参数的装饰器

def 有参数的装饰器(*args, **kwargs):
    def 装饰器名称(f):
        def wrapper(*args, **kwargs):
            if 条件:
                f(*args, **kwargs)
            else:
                # 报错并抛出异常 raise Error("xxxxxx")
        return wrapper
    return 装饰器名称

3. 装饰器底层原理

@timmer         # fun = timmer(fun)
def fun():
    pass

4. functools: 保留原有函数的名称(f.name)和文档帮助等信息;

def 装饰器名称(f):
    @functools.wrap(f)
    def wrapper(*args, **kwargs):
        if 条件:
            f(*args, **kwargs)
        else:
            # 报错并抛出异常 raise Error("xxxxxx")
    return wrapper

5. inspect:

    不管是默认参数, 必选参数, 可变参数, 关键子参数, 都会将形式参数和传的值封装为字典;便于使用;

"""

**例子1:
# 装饰器: 本质上是一个函数, 接收其他函数作为参数;对于原有的函数做了新的修改;
import random
import time


def addInfo(fun):   # fun: transferMoney
    def wrapper():
        print "六一儿童节快乐...."
        fun()   # transferMoney()
        print fun.__name__
        print "欢迎使用ICBC ATM......."
    return  wrapper

# python的语法糖:for i in s:
@addInfo
#     transferMoney = addInfo(transferMoney)  # 返回wrapper
def transferMoney():
    print "转账......."
# wrapper

transferMoney()

**例子2:
计时器
import random
import time
import functools

def timmer(fun):        # fun = login
    # 这个@functools.wraps(fun)可以保留函数原有的函数名和函数帮助文档;
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):
        """this is wrapper"""
        # args: tuple
        # kwargs: dict
        # 获取当前时间戳i
        start_time = time.time()
        # *args对元组进行解包;
        # **kwargs对字典进行解包的;
        fun(*args, **kwargs)           # fun()   ==== login()
        end_time = time.time()
        # 任何一个函数都有一个属性__name__,获取函数名称;
        print "%s 执行时间为%s" %(fun.__name__, end_time-start_time)
    return wrapper

@timmer
def fun1():
    print "func1....."
    # time.sleep: 休眠
    # random.random: 随即生成一个0~1之间的数;
    time.sleep(random.random())

@timmer
# login = timmer(login)
def login(name, password):
    """ user login
    """
    if name == 'root' and password == 'redhat':
        print 'login ok'
    else:
        print 'login fail'

if __name__ == "__main__":
    login('root', 'westos')
    print login.__name__
    print login.func_doc

**例子3:
多个装饰器
def makebold(fn):
    def wrapper():
        return "<b>" + fn() + '</b>'
    return wrapper

def makeitalic(fn):
    def wrapper():
        return "<i>" + fn() + "</i>"
    return wrapper

@makebold  # <b>"hello world"</b>
@makeitalic #  <i><b>"hello world"</b></i>
def hello():
    return "hello world"

if __name__ == "__main__":
    print hello()

**例子4:
def counter(f):
    def wrapper(*args, **kw):
        wrapper.count += 1
        f(*args, **kw)
        print "%s has been used %s" %(f.__name__,wrapper.count)

    wrapper.count = 0
    return  wrapper

@counter
def fun():
    print "fun......."

@counter
def fun1():
    print "fun1......."
f1 = fun()
f2 = fun()
f3 = fun()
f4 = fun()
f5 = fun()

**例子5:
给装饰器传参
import random
import time

def add(name):      # name = "转账
    def addInfo(fun):   # fun: transferMoney
        def wrapper():
            print "六一儿童节快乐...."
            fun()   # transferMoney()
            print fun.__name__
            print "欢迎使用ICBC ATM...%s模块...." %(name)
        return  wrapper
    return addInfo

@add("转账")   # add = add("转账")
def transferMoney():
    print "欢迎来到ATM....."

@add("存钱")   # add = add("转账")
def saveMoney():
    print "欢迎来到ATM....."

transferMoney()
saveMoney()

**例子6:
import functools

def required_type(*args_type):
    # args_type: tuple
    def required_num(f):
        @functools.wraps(f)
        def wrapper(*args, **kwargs):
            # args:tuple
            # kwargs:
            # kwargs.values(): list
            for arg in args + tuple(kwargs.values()):
                print args_type
                if not isinstance(arg, args_type):
                    # 抛出异常
                    # f.__name__函数的名称
                    raise TypeError("[参数错误]: %s only accept nums as arguments;" % (f.__name__))
            #f: 是函数名, f():调用函数
            return f(*args, **kwargs)

        return wrapper
    return required_num

@required_type(int, float)
def add(a, b):
    return a + b

print  add(5, 1.0)

猜你喜欢

转载自blog.csdn.net/goddevin/article/details/79959760
今日推荐