首页 > 其他分享 >函数与装饰器

函数与装饰器

时间:2022-10-11 22:25:57浏览次数:49  
标签:index outer 函数 func time print 装饰 def

函数与装饰器

目录

global与nonlocal

1、global关键字用来在函数或其他局部作用域中使用全局变量,如果不修改全局变量也可以不使用global关键字。

age = 18
def index():
    global age
    age = 88
index()
print(age)
# 88 局部名称空间直接修改全局名称空间中的数据

2、对于嵌套多层的函数,使用nonlocal关键字可以将名字声明为来自外部嵌套函数定义的作用域(非全局)

def index():
    name = 'jason'
    def inner():
        nonlocal name
        name = 'lily'
    inner()
    print(name)
index()
# lily 内层局部名称空间修改外层局部名称空间中的数据
    

函数名的多种用法

函数名其实绑定的也是一块内存地址,该地址里面存放的是一段代码,使用函数名加括号就会找到该代码并执行。

1、当做变量名赋值

def index():pass
name = index
name()
print(name)
# <function index at 0x00000214183F6670>
# name的输出结果就等于index

2、当作函数的参数

def index():
    print('from index')
 
def func(a):
    print(a)# a = index
    a()     # index()

func(index)
# from index index被作为函数参数调用

3、当做函数的返回值

def index():
    print('from index')

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

res = func()# from func 
print(res) # 执行完print('from func')后返回到index,此时打印res就等于打印index的内存地址
res()# from index,此时res()=index()

def index():
    print('from index')

    def func():
        print('from func')
    return func

res = index()# from index
print(res) 
# res = index(),相当于此时打印的是index的内存地址
res() # from func,因为func在index的里面,return func这行代码改变了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('功能编号不存在')
  # 此处if条件代替了以往需要重复的if...elif...else条件代码

闭包函数

闭包函数是定义在函数内部但用到了外部函数名称空间中的名字的函数。

  • 1.定义在函数内容
  • 2.用到外部函数名称空间中的名字
def index():
    age = 18
    def inner():
        print(age)
    return inner
a=index()
a()
# a()=inner() ,a使用index的值,但内存地址与inner一样

闭包函数实际应用
 # 给函数体代码传参的方式1:代码里面缺什么变量名形参里面就补什么变量名
    def register(name,age):
        print(f"""
       姓名:{name}
       年龄:{age}
         """)
        register('jason', 18)
     给函数体代码传参的方式2:闭包函数
    def outer(name, age):
        # name = 'jason'
        # age = 18
        def register():
            print(f"""
            姓名:{name}
            年龄:{age}
            """)
        return register
    res = outer('jason', 18)
    res()# 不添加值,默认是('jason',18)
    res = outer('kevin', 28)
    res()# 不添加值,默认是('kevin',28)

装饰器简介

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)

装饰器推导流程

1直接在调用index函数后面添加后代
import time
def index():
    time.sleep(3)
    print('from index')
def home():
    time.sleep(1)
    print('from home')
start_time = time.time()
index()
end_time = time.time()
print('函数index的执行时间为>>>:', end_time-start_time)
2.index调用的地方较多 代码不可能反复拷贝>>>:相同的代码需要在不同的位置反复执行>>>:函数
import time
def index():
    time.sleep(3)
    print('from index')
def home():
    time.sleep(1)
    print('from home')
def get_time():
    start_time = time.time()
    index()
    end_time = time.time()
    print('函数index的执行时间为>>>:', end_time - start_time)
get_time()
3..函数体代码写死了 只能统计index的执行时间 如何才能做到统计更多的函数运行时间 直接传参变换统计的函数
import time
def index():
    time.sleep(3)
    print('from index')
def home():
    time.sleep(1)
    print('from home')
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.虽然实现了一定的兼容性 但是并不符合装饰器的特征  第一种传参不写 只能考虑闭包
import time
def index():
    time.sleep(3)
    print('from index')
def home():
    time.sleep(1)
    print('from home')
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.调用方式还是不对 如何变形>>>:变量名赋值绑定
import time
def index():
    time.sleep(3)
    print('from index')
def home():
    time.sleep(1)
    print('from home')
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.上述装饰器只能装饰无参函数 兼容性太差
import time
def func(a):
    time.sleep(0.1)
    print('from func', a)

def func1(a,b):
    time.sleep(0.2)
    print()
6.上述装饰器只能装饰无参函数 兼容性太差
import time
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.被装饰的函数不知道有没有参数以及有几个参数 如何兼容
import time
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.如果被装饰的函数有返回值
import time
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)     

装饰器模板

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

装饰器语法糖

 语法糖:
       @装饰器名字
@outer
写在被装饰函数定义之前单独一行(必须先定义装饰器outer)
用来使函数调用时尽量与原函数没有操作上的不同
同样的,不想使用装饰器功能时删除此行即可
def outer(func_name):
    def inner(*args, **kwargs):
        print('执行被装饰对象之前可以做的额外操作')
        res = func_name(*args, **kwargs)
        print('执行被装饰对象之后可以做的额外操作')
        return res
    return inner
"""
语法糖会自动将下面紧挨着的函数名当做第一个参数自动传给@函数调用
"""
@outer  
def func():
    print('from func')
    return 'func'
# func = outer(func)

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

func()
index()

标签:index,outer,函数,func,time,print,装饰,def
From: https://www.cnblogs.com/zhiliaowang/p/16782842.html

相关文章

  • 函数名的多种用法及装饰器
    目录global与nonlocal关键字函数名的多种使用方法闭包函数装饰器简介装饰器推导流程装饰器模板装饰语法糖global与nonlocal关键字global关键字"""局部名称空间直接修......
  • 装饰器小节
    目录global与nonlocal函数名的多种用法闭包函数装饰器简介无参装饰器有参装饰器装饰器模板装饰器语法糖及修复技术今日内容详解global与nonlocalmoney=......
  • python装饰器初级
    global与nonlocal1.global的作用:可以在局部空间里直接就该全局名称工具中的数据代码展示:name='moon'#设置了一个全局变量deffucn():name='god'#......
  • 装饰器推导
    importtimedefindex():time.sleep(3)print('fromindex')defhome():time.sleep(1)print('fromhome')'''1.直接在调用index函数的前后添加代......
  • 函数
    global与nonlocal一、global总之一句话,作用域是全局的,就是会修改这个变量对应地址的值。global语句是一个声明,它适用于整个当前代码块。这意味着列出的标识符将被解释为......
  • 闭包函数与装饰器
    昨日内容回顾函数的参数位置参数 分为位置形参和位置实参,位置形参与实参数量要一致,使用关键字传参可改变赋值顺序。默认参数 函数定义阶段赋有默认值的参数,传参时可不......
  • 函数之装饰器
    global与nonlocal1.局部名称空间直接修改全局名称空间中的数据money=123defindex():globalmoneymoney=222index()print(money)2.内层局部名称空间修......
  • 函数(三)——闭包函数与装饰器
    一、函数名的多种用法函数名其实绑定的是一块内存地址,只不过该地址里面存放的不是数据值而是一段代码,函数名加括号就会找到该代码并执行。1. 可以当做变量名赋值defi......
  • 函数剩余内容/函数装饰器
    目录今日内容概要1.global与nonlocal用法2.函数名的多种用法3.闭包函数4.装饰器介绍5.装饰器原理推导过程6.装饰器模板7.装饰器语法糖练习题及答案今日内容概要global和......
  • 闭包函数与装饰器
    今日内容总结global与nonlocalmoney=666defindex():globalmoneymoney=123index()print(money)"""局部名称空间直接修改全局空间中的数据"""......