zoukankan      html  css  js  c++  java
  • 有参装饰器

    wraps装饰器补充
    偷梁换柱:即将原函数名(index)指向的内存地址偷梁换柱成wrapper,所以应该将wrapper做的跟原函数一样
    (1)
    def index(x,y):
    '''这个是主页功能'''
    print(x,y)
    index(1,2)

    print(index.__name__) # index
    print(help(index))
    help运行结果:
    Help on function index in module __main__:
    index(x, y)
    这个是主页功能

    (2)
    def outter(func):
    def wrapper(*args,**kwargs):
    res = func(*args,**kwargs)
    return res
    return wrapper

    根据账号密码不同来源验证登录:
    问题:需要传入参数db_type,而装饰器的outter函数只能传入被装饰对象函数地址一个参数
    low解决方法:
    def deco(func,db_type):
    def wrapper(*args,**kwargs):
    name = input('your name:').strip()
    pswd = input('your password:').strip()
    if db_type == 'file':
    print('基于文件的验证')
    if name == 'lili' and pswd == '1234':
    res = func(*args,**kwargs)
    return res
    else:
    print('user or password error')
    elif db_type == 'mysql':
    print('基于mysql的验证')
    elif db_type == 'ldap':
    print('基于ldap的验证')
    else:
    print('不支持该db_type')
    return wrapper

    def index(x,y):
    print('index %s %s'%(x,y))

    def home(name):
    print('home %s'%name)

    def transfer():
    print('transfer')

    index = deco(index,'file')
    home = deco(home,'mysql')
    transfer = deco(transfer,'ldap')

    index(11,22)
    home('lili')
    transfer()

    @outter
    def index(x,y):
    '''这个是主页功能'''
    print(x,y)
    index(1,2)

    print(index.__name__) # wrapper
    print(help(index)) help(index) 相当于 index.__doc__
    help查看注释信息运行结果:
    Help on function wrapper in module __main__:
    wrapper(*args, **kwargs)

    以上情况对比发现:加入装饰器后的index函数与原先的index函数的一些属性上是发生了改变的,并不是真正的原始的index

    解决方案:
    from functools import wraps 导入
    def outter(func):
    @wraps(func) # 将func的所有属性赋值给wrapper
    def wrapper(*args,**kwargs):
    res = func(*args,**kwargs)
    return res
    return wrapper

    @outter
    def index(x,y):
    '''这个是主页功能'''
    print(x,y)
    index(1,2)

    print(index.__name__) # index
    print(index.__doc__) # 这个是主页功能
    这一步骤是更加细化装饰过程,使装饰后的index与原始index返回值、属性等一致

    外层包一个函数用于传参db_type
    分析:
    def auth(db_type):
    def deco(func):
    .....
    return deco
    deco = auth(db_type = 'file')

    @deco
    def index(x,y):
    print('index %s %s'%(x,y))
    @deco
    def home(name):
    print('home %s'%name)
    @deco
    def transfer():
    print('transfer')

    index(11,22)
    home('lili')
    transfer()
    结果三者来源都为file,而没有区分出基于mysql和ldap的验证

    优化:
    def auth(db_type):
    def deco(func):
    def wrapper(*args,**kwargs):
    name = input('your name:').strip()
    pswd = input('your password:').strip()
    if db_type == 'file':
    print('基于文件的验证')
    if name == 'lili' and pswd == '1234':
    res = func(*args,**kwargs)
    return res
    else:
    print('user or password error')
    elif db_type == 'mysql':
    print('基于mysql的验证')
    elif db_type == 'ldap':
    print('基于ldap的验证')
    else:
    print('不支持该db_type')
    return wrapper
    return deco

    @auth(db_type='file')
    def index(x,y):
    print('index %s %s'%(x,y))

    @auth(db_type='mysql')
    def home(name):
    print('home %s'%name)

    @auth(db_type='ldap')
    def transfer():
    print('transfer')

    index(1,22) # wrapper(1,22)
    home('lili') # wrapper('lili')
    transfer()

    一个函数多个装饰器

    def decorator_a(func):
    print('this is decorator_a')
    def inner_a(*args,**kwargs):
    print('this is inner_a')
    return func(*args,**kwargs)
    return inner_a

    def decorator_b(func):
    print('this is decorator_b')
    def inner_b(*args,**kwargs):
    print('this is inner_b')
    return func(*args,**kwargs)
    return inner_b

    @decorator_b
    @decorator_a
    def f(x):
    print('this is f')
    return x*2
    f(1)

    运行结果:
    this is decorator_a
    this is decorator_b
    this is inner_b
    this is inner_a
    this is f
    程序开始执行decorator函数内部的内容,一开始它又碰到了一个函数inner,inner函数定义块被程序观察到后不会立刻执行,而是读入内存中(这是默认规则)

    - 就近原则
    - 说明装饰器函数在被装饰函数定义好后就立即执行。
    - 而且执行顺序是由下到上开始装饰。调用decorator_a时,f被装饰成inner_a,调用decorator_b时,f被装饰成inner_b。因此,装饰顺序是”就近原则“

    — 就远原则
    - 通过打印f发现,f最终被装饰成了()。
    - 而inner_b中return的func,实则为inner_a, inner_a中return的func才是最终的f,所以最后的调用顺序为inner_b --->inner_a--->f。因此执行顺序为”就远原则“

    有参装饰器总结:
    from functools import wraps
    def 有参装饰器(x,y,z):
    def outter(func):
    @wraps(func) # 将func的所有属性赋给wrapper
    def wrapper(*args,**kwargs):
    res = func(*args,**kwargs)
    return res
    return wrapper
    return outter

    @有参装饰器(1,y=2,z=3)
    def 被装饰对象():
    pass
    被装饰对象()

  • 相关阅读:
    DWZ中刷新dialog的方案解决
    C#开源资源
    css 布局
    js 事件
    css 1-3
    get post
    jquery ..... deferred
    arguments -- 仅仅是百度面试问了一下,大致就这些。不深
    git push
    [转载] ie 8 兼容性, 最重要的一点是,xp 最高支持ie8
  • 原文地址:https://www.cnblogs.com/python-htl/p/15251555.html
Copyright © 2011-2022 走看看