python装饰器基础

 什么是装饰器:

给已有函数增加额外功能的函数,本质上是一个闭包。

装饰器功能特点:

1.不修改已有代码。

2.不修改已有函数的调用方式。

3.给已有函数增加额外功能。

装饰器的标准使用:

def count_time(func):
    def inner():
        start = time.time()
        func()
        end = time.time()
        print(f'共用时{end-start} 秒')

    return inner

@count_time
def show():
    n = 0
    for i in range(1000000):
        n += 1
    print('show - ',i)



show()

将show传给inner中的func。此时:show = count_time(show)。

结果是:

如果要给装饰器传递参数或者返回参数该怎么办呢?

python里还定义了一个通用装饰器。

通用装饰器:

# 定义一个通用装饰器(可以适合任何个数的参数)
def outerall(func):
    def inner(*args,**kwargs):
        print('装饰内容1:。。。。')
        ret = func(*args,**kwargs)
        print("装饰内容2:。。。")
        return ret
    return inner

@outerall
def showall(n,msg):
    print(str(n) + msg)
    print(type(n))
    print(type(msg))

showall(1,'hahahaha')

结果为: 

 从中可以看出使用*args,**kwargs来作为接收元组,字典。通过这个通用装饰器即可实现多个参数的传输,返回。

多个装饰器的使用:

从下到上装饰,从上到下执行。

# 第一个闭包
def wrapper_div(func):
    def inner(*args,**kwargs):
        return '<div>' + func(*args,**kwargs) + '</div>'
    return inner

# 第二个闭包
def wrapper_p(func):
    def inner(*args,**kwargs):
        return '<p>' + func(*args,**kwargs) + '</p>'
    return inner

# 定义一个函数
@wrapper_div
@wrapper_p
def show():
    return 'short life I use py'

print(show())

结果是: 

 

就和糖衣一样,wrapper_div装饰在最上面,那么它显示的结果就在最外面,wrapper_p装饰器在div装饰器下面 ,它就在div装饰的里面。最里面就是内函数。 

类装饰器:

使用类来作为装饰器。

class wrapper():
    def __init__(self,func):
        self.func = func
    def __call__(self, *args, **kwargs):
        print('装饰内容1.。。。')
        ret = self.func()
        print('装饰内容2.。。。')
        return ret

@wrapper
def show():       # show = wrapper(show)
    print('show run...')
show()

 结果是:

可见:

#  如果是一个类实现的装饰器,那么该装饰器执行完成后,被装饰函数指向该类的实例对象
#  如果能让被装饰函数正常执行,那么在改实例对象的类中实现 __call__方法,就相当于闭包中的内函数
#  一旦被装饰的函数执行调用,那么就回去执行实例对象里的__call__函数

带有参数的装饰器:

就是使用装饰器装饰函数时,可以传入指定参数。


def set_arg(msg):
    def set_func(func):
        def inner():
            print('装饰内容1....' + msg)
            func()
        return inner
    return set_func


@set_arg('hello')
def show():
    print('show run...')

show()

无论闭包函数定义成什么样 在使用该闭包进行装饰函数时 被装饰的函数 永远指向闭包函数的内函数。

有参数装饰器的应用:

实现一个自动维护的网页(大概)。

路由: 通过一个路径 可以去找到一个资源的地址。
# 定义一个网页的空字典
router_table = {}


# 定义一个用来自动维护路由的装饰器(带参)
def router(url):
    def wrapper(func):
        def inner():
            print('inner -',func)
            func()
        # 在这里维护路由表
        router_table[url] = inner
        return inner
    return wrapper

@router('index.html')
def index():
    print('首页')

@router('center.html')
def center():
    print('个人中心')

@router('maill.html')
def mail():
    print('邮箱页面')

def error():
    print('访问页面不存在')




def request(url):
    # 先定义一个函数,指向错误页面
    func = error
    # 判断请求的url是否在字典里 如果在字典里 那么使用url 作为key,取出作为函数引用
    if url in router_table:
        func = router_table[url]

    # 执行
    func()

request('index.html')
request('center.html')
request('login.html')

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值