装饰器

导读:本篇文章讲解 装饰器,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

今日内容概要

  • global and nonlocal
  • 函数名的多种用法
  • 闭包函数
  • 装饰器简介
  • 无参装饰器
  • 有参装饰器
  • 装饰器模板
  • 装饰器语法糖及修复技术
  • 多层装饰器

今日内容详细

globa and nonlocal

money = 666
def index():
    global money
    money = 123
index()
print(money)
"""
局部名称空间直接修改全局名称空间的数据
"""

def index():
    name = 'almira'
    def inner():
        nonlocal name
        name = 'lina'
    inner()
    print(name)
index()
"""
内层局部名称空间修改外粗局部名称空间的数据
"""

函数名的多种用法

变量名和函数名绑定的都是一块内存地址,
变量名绑定的内存地址里面存放的是数据值
函数名绑定的内存地址里面存放的的一段代码
函数名加括号就会找到该代码并执行
1.可以当作变量名赋值
    def index():pass
    res = index
    res()
2.可以当作函数的参数
    def index():
        print('from index')
    def func(a):
        print(a)
        a()
    func(index)
3.可以地址函数的返回值
    def index():
        print('from index')
    def func():
        print('from func')
        return index
    res = func()
    print(res)
    res()

    def index():
        print('from index')
        def func():
            print('from func')
        return func
    res = index()
    print(res)
    res()

4.可以当作容器类型的数据
    # 定义容器类型
    def register():
        print('注册功能')


    def login():
        print('登陆成功')


    def withdraw():
        print('提现功能')


    def transfer():
        print('转账功能')


    def shopping():
        print('购物功能')


    # 定义功能编号与功能的对应关系
    func_dict = {
        '1': register,
        '2': login,
        '3': withdraw,
        '4': transfer,
        '5': shopping
    }
    while True:
        print("""
        1.注册功能
        2.登录功能
        3.提现功能
        4.转账功能
        5.购物功能
        """)
        choice = input('>>>:').strip()
        if choice in func_dict:
            func_name = func_dict.get(choice)
            func_name()
        else:
            print('功能编号不存在')

闭包函数

"""
定义:
	1.定义在函数内容
	2.用到外部函数名称空间的名字
"""
def index():
    name = 'almira'
    def inner():
        print(name)
        
        
闭包函数的实际应用>>>:函数体代码传参
    # 方式1:代码里缺什么变量名形参里面就补什么变量名
    def register(name,age):
        print(f"""
        姓名:{name}
        年命:{age}
        """)
    register('almira',24)

    # 方式2:闭包函数
    def outer(name,age):
        # name ='almira'
        # age = 24
        def register():
            print(f"""
            姓名:{name}
            年龄:{age}
            """)
        return register
    res = outer('almira',18)
    res()
    res()
    res = outer('lina',22)
    res()
    res()
    res()

    

装饰器简介

1.概念
	在不改变装饰器对象原代码和调用方式的情况下给被装饰对象添加新的功能
2.本质
	装饰器不是一门新的技术 而是由函数参数、名称空间、函数名多种用法、闭包函数组合到一起的结果
 3.口诀
	对修改封闭 对扩展开放
4.储备知识
	时间相关操作
     import time
    # print(time.time())  # 时间戳(距离1970-01-01 00:00:00所经历的秒数)
    time.sleep(3)
    print('睡醒了 干饭')

    # count = 0
    # 循环之前先获取时间戳
    # start_time = time.time()
    # while count < 100:
    #     print('哈哈哈')
    #     count += 1
    # end_time = time.time()
    # print('循环消耗的时间:', end_time - start_time)

装饰器推到流程

import time


def index():
    time.sleep(3)
    print('from index')
def home():
    time.sleep(1)
    print('from home')
'''1.直接在调用index函数的前后添加代码'''
# start_time = time.time()
# index()
# end_time = time.time()
# print('函数index的执行时间为>>>:', end_time-start_time)
'''2.index调用的地方较多 代码不可能反复拷贝>>>:相同的代码需要在不同的位置反复执行>>>:函数'''
# def get_time():
#     start_time = time.time()
#     index()
#     end_time = time.time()
#     print('函数index的执行时间为>>>:', end_time - start_time)
# get_time()
'''3.函数体代码写死了 只能统计index的执行时间 如何才能做到统计更多的函数运行时间 直接传参变换统计的函数'''
# def get_time(xxx):
#     start_time = time.time()
#     xxx()
#     end_time = time.time()
#     print('函数的执行时间为>>>:', end_time - start_time)
# get_time(index)
# get_time(home)
'''4.虽然实现了一定的兼容性 但是并不符合装饰器的特征  第一种传参不写 只能考虑闭包'''
# def outer(xxx):
#     # xxx = index
#     def get_time():
#         start_time = time.time()
#         xxx()
#         end_time = time.time()
#         print('函数的执行时间为>>>:', end_time - start_time)
#     return get_time
# res = outer(index)
# res()
# res1 = outer(home)
# res1()
'''5.调用方式还是不对 如何变形>>>:变量名赋值绑定 (******)'''
# def outer(xxx):
#     def get_time():
#         start_time = time.time()
#         xxx()
#         end_time = time.time()
#         print('函数的执行时间为>>>:', end_time - start_time)
#     return get_time
# res = outer(index)  # 赋值符号的左边是一个变量名 可以随意命名
# res1 = outer(index)
# res2 = outer(index)
# jason = outer(index)
# index = outer(index)
# index()
# home = outer(home)
# home()
'''6.上述装饰器只能装饰无参函数 兼容性太差'''
# def func(a):
#     time.sleep(0.1)
#     print('from func', a)
#
# def func1(a,b):
#     time.sleep(0.2)
#     print('from func1', a, b)
#
# def func2():
#     time.sleep(0.3)
#     print('from func2')
# func(123)
# def outer(xxx):
#     def get_time(a, b):
#         start_time = time.time()
#         xxx(a, b)
#         end_time = time.time()
#         print('函数的执行时间为>>>:', end_time - start_time)
#     return get_time
# func1 = outer(func1)
# func1(1, 2)
# func = outer(func)
# func(1)
# func2 = outer(func2)
# func2()
'''7.被装饰的函数不知道有没有参数以及有几个参数 如何兼容'''
# def func(a):
#     time.sleep(0.1)
#     print('from func', a)
# def func1(a,b):
#     time.sleep(0.2)
#     print('from func1', a, b)
# def outer(xxx):
#     def get_time(*args, **kwargs):  # get_time(1,2,3)  args=(1,2,3)
#         start_time = time.time()
#         xxx(*args, **kwargs)  # xxx(*(1,2,3))    xxx(1,2,3)
#         end_time = time.time()
#         print('函数的执行时间为>>>:', end_time - start_time)
#     return get_time
# func = outer(func)
# func(123)
# func1 = outer(func1)
# func1(1, 2)
'''8.如果被装饰的函数有返回值'''
def func(a):
    time.sleep(0.1)
    print('from func', a)
    return 'func'
def func1(a,b):
    time.sleep(0.2)
    print('from func1', a, b)
    return 'func1'
def outer(xxx):
    def get_time(*args, **kwargs):
        start_time = time.time()
        res = xxx(*args, **kwargs)
        end_time = time.time()
        print('函数的执行时间为>>>:', end_time - start_time)
        return res
    return get_time
# func = outer(func)
# res = func(123)
# print(res)

func1 = outer(func1)


res = func1(123, 123)
print(res)

装饰器模板

# 务必掌握
    def outer(func):
        def inner(*args, **kwargs):
            res = func(*args, **kwargs)
            return res
        return inner
    
    
# 如何套模板?

def outer(func):
    def inner(*args, **kwargs):
        username = input('username>>>>:').strip()
        password = input('password>>>:').strip()
        if username == 'almira' and password == '12345':
            res = func(*args, **kwargs)
            print('执行被装饰对象之前 可以做的额外操作')
            return res
        else:
            print('执行被装饰对象之后 可以做的额外操作')
    return inner
@outer
def func2():
    print('登录成功')
    
# func2 = outer(func2)
func2()

函数装饰器语法糖

def outer(func_name):
    def inner(*args, **kwargs):
        print('执行被装饰对象之前可以做的额外操作')
        res = func_name(*args, **kwargs)
        print('执行被装饰对象之后可以做的额外操作')
        return res
    return inner
"""
语法糖会自动将下面紧挨着的函数名当做第一个参数自动传给@函数调用
"""
@outer  # func = outer(func)
def func():
    print('from func')
    return 'func'

@outer  # index = outer(index)
def index():
    print('from index')
    return 'index'

func()
index()

作业

编写一个用户认证装饰器
  函数:register login transfer withdraw 
  基本要求
   	 执行每个函数的时候必须先校验身份 eg: jason 123
        
def login_auth(func):
    def inner(*args, **kwargs):
        username = input('username>>>>:').strip()
        password = input('password>>>:').strip()
        if username == 'almira' and password == '12345':
            res = func(*args, **kwargs)
            print('登陆成功')
            return res
        else:
            print('用户名或密码错误')
    return inner

@login_auth
def register():
    print('注册功能')

@login_auth
def login():
    print('登陆功能')

@login_auth
def withdraw():
    print('提现功能')

@login_auth
def transfer():
    print('转账功能')



# 定义功能编号与功能的对应关系
func_dict = {
    '1': register,
    '2': login,
    '3': withdraw,
    '4': transfer,
}
while True:
    print("""
    1.注册功能
    2.登录功能
    3.提现功能
    4.转账功能
    """)
    choice = input('>>>:').strip()
    if choice in func_dict:
        func_name = func_dict.get(choice)
        func_name()
    else:
        print('功能编号不存在')

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/70032.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!