装饰器、global与nonlocal

global与nonlocal

global

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

nonlocal

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

函数名的多种用法

'''
函数名其实绑定的也是一块内存地址 只不过改地址里面存放的不是数据值而是一段代码 函数名加括号就会找到该代码并执行
'''

1、可以当作变量名赋值
def index():pass
    res = index
    res()
    
2、可以当作函数的参数
def index():
    print('from index')
def func(a):
    print(a)
    a()
func(index)
"""
<function index at 0x7fef880cd1f0>
from index
"""
3、可以当作函数的返回值
def index():
    print("from index")
def func():
    print("from func")
    return index
res=func()
print(res)
res()
"""
from func
<function index at 0x7fa6f80cd1f0>
from index
"""
4、可以当作容器类型(可以存放多个数据的数据类型)的数据
def login():
    print("login")
def shopping():
    print("shopping")
def register():
    print("register")
dict_app = {
    "1": login,
    "2": shopping,
    "3": register,
}
while True:
    c=input("command>>>")
    if c in dict_app:
        dict_app.get(c)()
    else:
        print("指令不存在")
"""
command>>>1
login
command>>>2
shopping
command>>>3
register
command>>>4
指令不存在
command>>>
"""

闭包函数

什么是闭包函数?

'''
定义在函数内部的函数 并且用到了外部函数名称空间的名字
1、定义在函数内容
2、用到外部函数名称空间中的名字
'''
闭包函数实际应用>>>:是另外一种给函数体代码传参的方式!!!
  # 给函数体代码传参的方式1:代码里面缺什么变量名形参里面就补什么变量名
def user(name):
    print(f"""
    hello,{name}
    """)
user("吴勇")
"""
hello,吴勇
"""
#给函数体代码传参的方式2:闭包函数
def func(name):
    # name = "吴勇"
    def user():
        print(f"""
        hello,{name}
        """)
    return user
res = func("吴勇")
res()
"""
hello,吴勇
"""

装饰器简介

1、概念
	在不改变被装饰对象源代码和调用方式的情况下给被装饰对象添加新的功能
2、本质
	由函数参数、名称空间、函数名多种用法、闭包函数组合到一起的结果
3、口诀
	对修改封闭 对扩展开发
4、储备知识
	时间相关操作
import time
start_time=time.time()
c=0
while c<100:
    print("我是为睡觉而生的高贵的羊,可不是你这种空有蛮力的沸羊羊能比的!")
    c=c+1
end_time=time.time()
print(end_time-start_time)#程序运行时间
"""
...
我是为睡觉而生的高贵的羊,可不是你这种空有蛮力的沸羊羊能比的!
我是为睡觉而生的高贵的羊,可不是你这种空有蛮力的沸羊羊能比的!
0.0002009868621826172
"""

装饰器推导流程

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_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()

作业

posted @ 2022-10-11 19:58  虾仁猪心排骨汤  阅读(39)  评论(0编辑  收藏  举报