py小强

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

这篇我们来介绍一下python中的装饰器。
这个内容涉及到了以前我们学习过的函数的各种知识,如果看不明白,可以到以前的笔记里面重新了解一下。

首先,什么是装饰器?

  • 实质:是一个函数
  • 参数:是你要装饰的函数名(此参数将指代被装饰函数)
  • 返回:装饰器的内部函数(非函数调用)
  • 特点:在装饰器内部函数内调用参数函数
  • 作用:为已经存在的对象函数添加额外的功能
  • 好处:不需要对对象函数做任何的代码上的变动

装饰器在函数定义的上一行调用

# 装饰器(又叫语法糖):在不改变原代码的前提下扩展功能(函数覆盖)。使用高阶函数和闭包。
user_info = {'alex': 'pwd', 'xiaoqiang': '123'}
login_status = False
payment = False

def login(func1):  # 装饰器的参数只能是想要覆盖的函数
    # 这个闭包的作用是:将函数体打包成一个函数来返回,配合高阶函数的函数赋值(把函数名赋值给变量),达到用同名变量覆盖原有函数的效果。
    def inner(*args,**kwargs):  # 用嵌套函数的闭包来实现:闭包可以把内部函数的内容的内存地址整个返回。
                  # 为了解决inner内部执行的函数有参数的问题,我们可以给inner和内部调用的函数加上万能参数*args,**kwargs
        global login_status  # 这个最好不用global

        if login_status == True:
            func1(*args,**kwargs)  # 这里不需要返回,而是执行

        else:
            username = input('username:')
            password = input('password:')

            if username in user_info.keys():

                if password == user_info[username]:
                    print('login succeed!')
                    login_status = True
                    func1(*args,**kwargs)
                else:
                    count = 0
                    while count < 2:
                        password = input('please input password again!:')
                        if password == user_info[username]:
                            print('login succeed!')
                            login_status = True
                            func1(*args,**kwargs)
                            break
                        else:
                            count += 1
                            if count == 2:
                                print('login failed!')
            else:
                print('no this user!')

    return inner  # 返回内部函数

def pay_money(func):

    def inner(*args, **kwargs):
        global payment
        if payment == True:
            print('you have paid!!')
        else:
            money = int(input('please input your money:'))

            if money >= 100:
                print('You have paid over 100rmb.Now you can do what you want to!!!')
                payment = True
                func(*args, **kwargs)
            else:
                print('not enough. You can not login!')

    return inner

def home():
    print('----首页----')

@pay_money  # 装饰器链:多个装饰器修饰函数。执行顺序是从近到远 @login-> @pay_money
@login  # 装饰器的语法,相当于下面同名变量覆盖原有函数的语句
def american():
    print('----欧美----')

@login
def japan(vip_level):  # 当原函数有参数
    if vip_level > 2:
        print('tokyo hot!')
    else:
        print('----日本----')

def henan():
    print('----河南----')


# american = login(american)  # 把闭包返回的函数内存地址用变量american接受,这个效果相当于定义函数。并且同名变量会覆盖原有函数
# # 这里的american赋值为login(american)情况下的inner 。执行的时候需要加()。
# japan = login(japan)

home()
american()  # 相当于执行inner
japan(4)  # 相当于执行inner(4)
  • 多层修饰器执行顺序(有点类似递归):
    多层修饰器修饰同一个函数的的时候,执行顺序是从近至远来执行的。
@deco1  # 第三执行,deco3-inner则会是最先被执行,然后一层一层往里挖。
@deco2  # 第二执行,return的结果deco2-inner会返回给deco1,deco2-inner压入栈里。
@deco3  # 最先执行,但是这个结构有点类似递归,return的结果(deco3的inner)会返回给deco2。所以deco3-inner会作为deco2的参数,会压在栈的最底层,会最后执行。
def func():
    pass

5.11 列表生成式(for)

用一行写出for循环赋值。

  • 特点:
    • 用一行的for循环来实现
    • for的表达式用[]括起来
    • 用来对列表内的元素遍历处理
a = [1,2,3,4,5,6,7]

a = [i+1 for i in a]  # 用for循环将列表的元素重新赋值并生成一个新列表。注意这里用[]

print(a)  # 直接生成了一个列表

扩展-复杂一点的列表生成式:

#### 请使用列表生成式将列表li = [1, 2, 3, 4, 5, 6, 7, 8, 9]中大于5的元素乘以2组成新的列表
li = [1, 2, 3, 4, 5, 6, 7, 8, 9]

li = [item * 2 for item in li if item > 5 ]

>其实列表生成器就是将生成器生成的元素直接转换成列表的一种方式。
posted on 2019-06-24 14:35  py小强  阅读(125)  评论(0)    收藏  举报