首页 > 编程语言 >python重点之装饰器

python重点之装饰器

时间:2022-10-11 20:33:31浏览次数:54  
标签:index 函数 python func time print 重点 装饰 def

  • global与nonlocal
  • 函数名的多种用法
  • 闭包函数
  • 装饰器简介
  • 无参装饰器
  • 有参装饰器
  • 装饰器模板
  • 装饰器语法糖

今日详细内容

global与nonlocal

    money = 666
    def index():
        global money  # 这句话表示直接将局部的money值改到全局空间
        money = 123
    index()
    print(money)
    # 局部名称空间直接修改全局名称中间中的数据

    def inder():
        name = 'jason'
        def inner():
            nonlocal name  # 直接将inder局部name值改为inner局部的
            name = 'kevin'
        inner()  # 这里调用函数inner
        print(name)
    inder()  # 调用函数inder
    # 内层局部名称空间修改外层局部名称空间中的数据

函数名多种用法

函数名其实绑定的也是一块内存地址,只不过该地址里面存放不是数据而是一段代码,函数名加括号就会找到该代码并执行
1.可以当做变量名赋值
def index():
    print('大帅哥')
res = index  # 将函数名index绑定的代码也赋值给res
res()  # res()就相当于index()
----------------------------------------------------------
2.也可以当做函数的参数
def index():
    print('from index')
def func(a):
    print('你真帅')
# a()
func(index)  # 直接打印函数func的函数体代码
----------------------------------------------------------
3.可以当做函数的返回值
def index():  # 定义函数index
    print('from index')
def func():  # 定义函数func
    print('from func')
    return index  # 函数func的返回值为index
res = func()  # 调用函数func打印然后返回值index绑定给res
print(res)  # 打印res其实就是函数名index绑定的代码
res()  # res()现在就是index()的意思
----------------------------------------------------------
4.可以当做容器类型(可以存放多个数据类型)的数据
def register():
    print('注册功能')


def lofin():
    print('登录功能')


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


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


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

# 定义功能编号与功能得对应关系
func_dice = {
    '1': register,
    '2': lofin,
    '3': withdraw,
    '4': transfer,
    '5': shopping
}
while True:
    print("""
    1.注册功能呢
    2.登录功能
    3.体现功能
    4.转账功能
    5.购物功能
    """)
    choice = input('请出去您想要执行的功能>>>:').strip()
    if choice in func_dice:  # 判断输入的选项在不在字典的键
        func_name = func_dice.get(choice)  # 字典按K取值到函数名,然后赋值给func_name
        func_name()  # func_name()相当于调用字典对应键的函数
    else:
        print('您输入的编号不存在')

闭包函数

"""
定义在函数内部的函数 并且用到了外部函数名称空间中的名字
	1.定义在函数内容
	2.用到外部函数名称空间中的名字
"""
def index():
    name = 'jason'
    def inner():
        print(name)  # name在index里面属于闭包函数
闭包函数实际应用>>>:是另外一种给函数体代码传参的方式!
----------------------------------------------------------
给函数体代码传参的方式1:代码里面缺什么变量名形参里面就补什么变量名
def register(name, age):  # 定义一个函数,两个位置形参
    print(f"""
    姓名:{name}
    年龄:{age}
    """)
register('jason', 18)  # 调用函数,给两个位置实参

给函数体代码传参的方式2:闭包函数
def outer(name, age):  # 定义一个函数,有两个位置形参
    def register():  # 在函数体代码中再定义一个函数,用到外层函数体代码的名字
        print(f"""
        姓名:{name}
        年龄:{age}
        """)

    return register  # outer函数体代码的返回值为register
res = outer('jason', 18)  # 调用函数outer两个位置函数,然后返回值赋值给res
res()  # 因为返回值为register绑定了res,所以res()其实就是register()
res = outer('a ning', 25)
res()

image

装饰器简介

1.概念
	在不改变被装饰对象原代码和调用方式的情况下给被装饰对象添加新的功能
2.本质
	并不是一门新的技术 而是由函数参数、名称空间、函数名多种用法、闭包函数组合到一起的结果
3.口诀
	对修改封闭 对扩展开放
4.储备知识
	时间相关操作
    import time
# print(time.time())  # 时间戳(距离1970.1.1的0时0分0秒所经历的秒数)
# time.sleep(5)  # 这句话意思是等5秒再走下一个代码
# print('吃饭吃饭')
count = 0  # 给存货一个计数器
# 循环之前先获取时间戳
star_time = time.time()  # 开始的时间给一个变量名
while count < 200:
    print('嘿嘿嘿')
    count += 1
end_time = time.time()  # 结束的时间给一个变量名
print('循环消耗的时间', end_time - star_time)  # 循环消耗的时间 0.0009741783142089844

装饰器推导流程

import time


def index():  # 定义一个函数
    time.sleep(3)  # 时间在这里停留3秒
    print('from index')  # 调用函数的时候打印from index


def home():  # 定义一个函数
    time.sleep(1)  # 时间在这里停留1秒
    print('from home')  # 调用函数的时候打印from home


"""1.直接在调用index函数的前后添加代码"""
# star_time = time.time()
# index()  # 调用index函数
# end_time = time.time()
# print('函数index的执行时间为>>>:', end_time - star_time)
"""2.第一种办法如果index调用的地方较多,代码反复拷贝增加工作量,考虑一点
相同的代码要在不同的位置反复执行等同于函数的概念"""
# def get_time():  # 定义一个函数,将办法1的包进去
#     star_time = time.time()
#     index()
#     end_time = time.time()
#     print('函数index的执行时间为>>>:', end_time - star_time)
# get_time()  # 调用定义的函数,然后index包在里面也会一起执行
"""3.第二种情况函数体就写死了,只能统计index的执行时间,如何才能做到统计
更多的函数运行时间,直接传参变换统计的函数"""
# def get_time(q1):  # 我们可以函数名传参,加一个位置形参
#     star_time = time.time()
#     q1()  # q1在局部空间找名字找不到向上找,就找到形参对应的实参index
#     end_time = time.time()
#     print('函数index的执行时间为>>>:', end_time - star_time)
# get_time(index)  # 调用get_time函数,传实参index给形参
"""4.第三种办法可以实现多个函数运行,但是并不符合装饰器的特征,第一种传参不写,
只能考虑闭包"""
# def outer(q):  #在外面在套一个函数
#     def get_time():  # 我们可以函数名传参,加一个位置形参
#         star_time = time.time()
#         q()  # q1名字因为在函数outer局部空间也存在所以属于闭包函数
#         end_time = time.time()
#         print('函数index的执行时间为>>>:', end_time - star_time)
#     return get_time
# 这里我们要调用的就是外面的函数outer
# res = outer(index)  # 调用函数outer实参传给q1形参,然后定义函数,outer返回值赋值给res
# res()  # res绑定的就是返回值get_time,所以调用res就是调用get_time
"""5.调用方法还是可以改变>>>变量名赋值绑定,最初是不改变函数的调用方式"""
# def outer(q):
#     def get_time():
#         star_time = time.time()
#         q()
#         end_time = time.time()
#         print('函数index的执行时间为>>>:', end_time - star_time)
#     return get_time
# res = outer(index)  # 变量名不止可以是res可以改变
# res1 = outer(index)
# index = outer(index)  # 括号内的index是传参给函数,等号左边的index是返回值所绑定的
# index()  # index绑定的就是get_time,执行index()实际还是执行get_time
"""6.上述装饰器只能装饰无参函数,兼容性太差"""
# def func(a):  # 定义函数
#     time.sleep(0.1)
#     print('from func', a)
# def func1(a, b):  # 定义函数
#     time.sleep(0.2)
#     print('form func1', a, b)
# def func2():  # 定义函数
#     time.sleep(0.3)
#     print('from func2')
# # func(123)  # 调用函数func给一个位置实参123,执行打印
# def outer(xxx):
#     def get_time(a, b):
#         star_time = time.time()
#         xxx(a, b)
#         end_time = time.time()
#         print('函数的执行时间为>>>:', end_time - star_time)
#     return get_time
# func1 = outer(func1)
# func1(1, 2)
"""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):
#         star_time = time.time()
#         xxx(*args, **kwargs)
#         end_time = time.time()
#         print('函数的执行时间为>>>:', end_time - star_time)
#     return get_time
# func1 = outer(func1)
# func1(1, 2)
# func = outer(func)
# func(1)
"""8.如果被装饰的函数有返回值"""
def func(a):  # 1.定义函数func
    time.sleep(0.1)
    print('from func', a)  # 10,执行
    return 'func'  # 11.将返回值赋值给get_time函数的变量名res
def func1(a, b):  # 2.定义函数func
    time.sleep(0.2)
    print('from func1', a, b)
    return 'func1'
def outer(xxx):  # 3.定义函数outer(形参)
    def get_time(*args, **kwargs):  # 接收多余的位置实参和关键字实参
        star_time = time.time()  # 8.执行
        res = xxx(*args, **kwargs)  # 将接收的位置实参和关键字实参打散9.执行函数xxx其实就是func函数 10.res现在就是func
        end_time = time.time()    # 11.执行
        print('函数的执行时间为>>>:', end_time - star_time)  # 12.执行
        return res  # 13.将返回值res赋值给变量名q1,而res又是函数func的返回值func
    return get_time  # 5.将返回值get_time赋值给func
# func = outer(func)  # 4.调用函数outer 6.func现在其实就是get_time
# q1 = func(1)  # 7.调用函数func也就是函数get_time  # 14.所以接收返回值res其实是func
# print(q1)  # 15.打印q1就是打印func
func1 = outer(func1)
res = func1(123, 321)
print(res)

装饰器模板

def outer(func):
    def inner(*args, **kwargs):
        # 执行被装饰对象之前可以做的额外操作
        res = func(*args, **kwargs)
        # 执行被装饰对象之后可以做的额外操作
        return res

    return inner

装饰器语法糖

def outer(w1):
    def inner(*args, **kwargs):
        print('函数体代码执行前想要添加的')
        res = w1(*args, **kwargs)
        print('函数体代码执行后想要添加的')
        return res

    return inner

"""
语法糖会自动将下面紧挨着的函数名当做第一个参数自动传给@函数调用
"""
@outer
def func(a):
    print('你真帅')
    return 'func'

func(1)
作业:
def outer(func):
    def inner(*args, **kwargs):
        username = input('请输入您的账号>>>:').strip()
        password = input('请输入您的密码>>>:').strip()
        if username == 'jason' and password == '123':
            print('登录成功')
        else:
            print('您的账号密码错误')
        res = func(*args, **kwargs)
        return res

    return inner


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


@outer
def login():
    print('登录功能')


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


@outer
def withdraw():
    print('体现功能')


func_dice = {
    '1': register,
    '2': login,
    '3': transfer,
    '4': withdraw,
}
print("""
1.注册
2.登录
3.转账
4.体现
""")
while True:
    choice = input('请输入您想要执行的编号>>>:').strip()
    if choice in func_dice:
        func_ll = func_dice.get(choice)
        func_ll()

标签:index,函数,python,func,time,print,重点,装饰,def
From: https://www.cnblogs.com/zhanghong1229/p/16782460.html

相关文章

  • 装饰器、global与nonlocal
    目录global与nonlocal函数名的多种用法闭包函数装饰器简介装饰器推导流程装饰器模版装饰器语法糖作业global与nonlocalglobalmoney=666defindex():globalmone......
  • python进阶之路11 闭包函数 装饰器
    函数名的多种用法函数名其实绑定的也是一块内存地址只不过该地址里面存放的不是数据值而是一段代码函数名加括号就会找到该代码并执行1.可以当作变量名赋值defindex......
  • Python爬虫-scrapyd框架部署
    爬虫项目部署1脚本文件部署linux内置的cron进程能帮我们实现这些需求,cron搭配shell脚本,非常复杂的指令也没有问题。1.1crontab的使用crontab[-uusername]/......
  • 函数名的用法,闭包函数与装饰器
    函数的多种用法与装饰器global与nonlocal1.global用在局部名称空间直接修改全局名称空间中的数据x=111deffunc():globalx#修改全局名称空间x值x=2......
  • Python基础12
    今日内容概要global与nonlocal函数名的多种用法闭包函数装饰器简介装饰器推导流程装饰器模板装饰器语法糖今日内容详细global与nonlocal'''通过global声明可......
  • 装饰器+闭包掌握(python一大重要功能)
    目录global与nonlocal函数名的多种用法闭包函数装饰器简介1.概念2.本质3.口诀4.超前知识time模块装饰器推导装饰器模板装饰器语法糖作业global与nonlocalglobal#提升......
  • Java设计模式之 装饰模式实验报告书
    Java设计模式之装饰模式实验报告书姓名:班级:学号:实验三:装饰模式的应用一、实验目的熟练使用JAVA实现装饰模式,理解设计模式的模式动机,掌握模式结构,学习如何使用代码实现......
  • 函数装饰器
    global与nonlocalmoney=666defindex():globalmoneymoney=123index()print(money)"""局部名称空间直接修改全局名称空间中的数据"""defindex(......
  • 将Curl转为Python的方法
    怎样将Curl转为Python的方法作为一名后端程序员,在服务器调试的过程中,使用curl命令为我们调试接口带来了很多的方便,极大地提高了效率;如下可以实现Get请求:curl'http://ba......
  • 函数名的多种用法及装饰器
    目录global与nonlocal函数名的多种用法闭包函数装饰器简介装饰器推导流程装饰器模板装饰器语法糖作业global与nonlocalmoney=666defindex():globalmoneym......