• 20181130(装饰器补充,叠加多个装饰器,有参装饰器,三元表达式,生成式,匿名函数,内置函数)


     

    一、装饰器的补充

    1、函数属性的传递

    Python装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,Python的functools包中提供了一个叫wraps的decorator来消除这样的副作用。写一个decorator的时候,最好在实现之前加上functools的wrap,它能保留原有函数的名称和docstring。
    简言之:导入wraps,即可将原函数的属性(解释文本等)传递给装饰器中对应的函数。
    from functools import wraps  #从 functools导入wraps

    def outter(func):
       @wraps(func)  #相当于一个装饰器,将func的属性传递给wraps
       def wrapper(*args,**kwargs):
           res=func(*args,**kwargs)
           return res
       return wrapper

    @outter #index=outter(index) #index=wrapper
    def index():
       """
      这是index函数....
      """
       print('from index')


    index()
    print(index.__doc__)  #输出index的说明文档
    print(index.__name__)  #输出index的名字,index是函数的内存地址
    输出结果为:
    from index

       这是index函数....
       
    index

     

    1、叠加多个装饰器

    加载顺序(outter函数的调用顺序):自下而上

    执行顺序(wrapper函数的执行顺序):自上而下

    # 叠加多个装饰器
    # 1. 加载顺序(outter函数的调用顺序):自下而上
    # 2. 执行顺序(wrapper函数的执行顺序):自上而下


    def outter1(func1): #func1=wrapper2的内存地址
       print('加载了outter1')
       def wrapper1(*args,**kwargs):
           print('执行了wrapper1')
           res1=func1(*args,**kwargs)
           return res1
       return wrapper1

    def outter2(func2): #func2=wrapper3的内存地址
       print('加载了outter2')
       def wrapper2(*args,**kwargs):
           print('执行了wrapper2')
           res2=func2(*args,**kwargs)
           return res2
       return wrapper2

    def outter3(func3): # func3=最原始的那个index的内存地址
       print('加载了outter3')
       def wrapper3(*args,**kwargs):
           print('执行了wrapper3')
           res3=func3(*args,**kwargs)
           return res3
       return wrapper3



    @outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址
    @outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址
    @outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址
    def index():
       print('from index')

    print('======================================================')
    index()
    输出结果为:
    加载了outter3
    加载了outter2
    加载了outter1
    ======================================================
    执行了wrapper1
    执行了wrapper2
    执行了wrapper3
    from index

     

     

    import time

    def timmer(func):
       def aaa(*args,**kwargs):
           start=time.time()
           res=func(*args,**kwargs)
           stop=time.time()
           print('run time is %s' %(stop -start))
           return res
       return aaa

    def auth(func):
       def bbb(*args,**kwargs):
           name=input('name>>>: ').strip()
           pwd=input('pwd>>>: ').strip()
           if name == 'egon' and pwd == '123':
               print('login successfull')
               res=func(*args,**kwargs)
               return res
           else:
               print('user or pwd error')
       return bbb

    @auth
    @timmer  #注意此处装饰器的先后顺序,调整装饰器的先后顺序,会得到不同的结果。
    def index():
       time.sleep(1)
       print('from index')

    index()

     

    2、有参装饰器:三层的闭包函数

    对于装饰器,三层就够了(第一层传参数,第二层传函数,第三层执行添加的功能和源代码)

    import time
    from functools import wraps
    current_user={'user':None}

    def auth(engine='file'):
       def outter(func):
           @wraps(func)
           def wrapper(*args,**kwargs):
               if current_user['user'] is not None:
                   res=func(*args,**kwargs)
                   return res

               user=input('username>>>: ').strip()
               pwd=input('password>>>: ').strip()

               if engine == 'file':
                   # 基于文件的认证
                   if user == 'egon' and pwd == '123':
                       print('login successfull')
                       current_user['user']=user
                       res=func(*args,**kwargs)
                       return res
                   else:
                       print('user or password error')
               elif engine == 'mysql':
                   # 基于mysql的认证
                   print('基于mysql的认证')
               elif engine == 'ldap':
                   # 基于ldap的认证
                   print('基于ldap的认证')
               else:
                   print('不知道engine')
           return wrapper
       return outter

    @auth('ldap') #@outter #index=outter(index) # index=wrapper #注意此处传参的方法
    def index():
       time.sleep(1)
       print('from index')

    @auth('mysql') #@outter # home=outter(home) #home=wrapper #注意此处传参的方法
    def home(name):
       print('welcome %s' %name)

    index()
    home('egon')

    输出结果:
    username>>>: egon
    password>>>: 123
    基于ldap的认证
    username>>>: egon
    password>>>: 123
    基于mysql的认证

     

    二、三元表达式

    只能将if else这种简单的取代,有elif的不行。

    res='ok' if False else 'no'  #条件成立输出左侧的值,否则输出右侧的值,可以简化if。。。else语句。
    print(res)
    输出结果为:
    no
    三、生成式

    列表生成式

    # l=[]
    # for i in range(10):
    #     if i>4:
    #         l.append(i**2)
    # print(l)  
    上下代码功能一致
    l=[i**2 for i in range(10) if i >4]  #后面不能使用else,无论是if else还是for else,可以对循环的参数进行操作
    print(l)
    输出结果为:
    [25, 36, 49, 64, 81]


    # 映射和判断
    names=['egon','go_on','kevin','wxx']
    print([name.upper() for name in names]) #映射关系
    print([name for name in names if name.endswith('on')])  #判断关系
    print([name.upper() for name in names if name.endswith('on')])  #映射叠加判断关系
    输出的结果:
    ['EGON', 'GO_ON', 'KEVIN', 'WXX']
    ['egon', 'go_on']
    ['EGON', 'GO_ON']

     

    字典生成式:key和value需要有对应关系才好处理。

    res={i:i**2 for i in range(10) if i > 3} #注意字典的生成格式
    print(res)

    print({i for i in 'hello'})  #注意此处生成的是集合!
    输出结果为:
    {4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
    {'e', 'h', 'l', 'o'}

     

    四、匿名函数:匿名函数就是只定义了一个函数的内存地址,主要用于临时使用一次的场景。
    a=(lambda x,y:x+y)(1,2)  #格式为“lambda 参数:表达式”后接括号内输入参数,匿名函数自带return,可以得到返回值
    print(a)
    输出结果为3

     

    五、内置函数

    1、max和min

    print(max([10,11,-3,23]))  #max会从列表中先取出两个值比较,再将较大的和下一个值比较
    输出结果为:
    23
    比较value的值,然后输出对应的key:
    salaries={
       'egon':3000,
       'alex':100000000,
       'wupeiqi':10000,
       'yuanhao':2000
    }

    def func(k):
       return salaries[k]

    print(max(salaries,key=lambda k:salaries[k]))  #此处第一个salaries是一个序列,其中的元素会被遍历,作为参数k进行函数的运算,不理解的话看下面
    print(min(salaries,key=func))  #其实没有必要做成有名函数,匿名函数就可以了。
    # for循环的结果         比较依据
    # 'egon'               3000
    # 'alex'               100000000
    # 'wupeiqi'             10000
    # 'yuanhao'             2000
    输出结果为:
    alex
    yuanhao

    max的解释:
    max(iterable, *[, key, default])
    max(arg1, arg2, *args[, key])
    字典是可迭代的,结果为key值,
    salaries={
       'egon':3000,
       'alex':100000000,
       'wupeiqi':10000,
       'yuanhao':2000
    }

    l=list(salaries)
    print(l)
    输出结果为:
    ['egon', 'alex', 'wupeiqi', 'yuanhao']

    res=max((1,2),[1,1],key = lambda x : x[1])
    print(res)
    输出结果为:
    (1, 2)

    sorted函数:

    def sorted(*args, **kwargs): # real signature unknown
      """
      Return a new list containing all items from the iterable in ascending order.
       
      A custom key function can be supplied to customize the sort order, and the
      reverse flag can be set to request the result in descending order.
      """
       
    以升序返回包含iterable中所有项的新列表。
    可以提供自定义键功能来自定义排序顺序,以及可以设置反向标志以按降序请求结果。

     

    匿名函数与其他函数的结合应用:

    salaries={
       'egon':3000,
       'alex':100000000,
       'wupeiqi':10000,
       'yuanhao':2000
    }
    print(sorted(salaries,key=lambda k:salaries[k],reverse=True)) #字典中的key变成序列作为参数传入后面的匿名函数,由升序改为降序排列。
    输出结果为:
    ['alex', 'wupeiqi', 'egon', 'yuanhao']

     

     

     

  • 相关阅读:
    Flutter 开发环境搭建
    swift 如何控制view的显示与隐藏
    TextView textSize 文字大小
    Android项目增加混淆
    Android EditText 无法换行
    Android 6.0 新特性 整理 资料来自网络
    java线程中的sleep/wait/notify/yield/interrupt方法 整理
    java 抽象类与接口的区别 整理
    android 系统架构
    android handler工作原理
  • 原文地址:https://www.cnblogs.com/realadmin/p/10046685.html
Copyright © 2020-2023  润新知