global与nonlocal、函数名用法、闭包函数、装饰器

内容回顾

  • global与nonlocal
  • 函数名的多种用法
  • 闭包函数
  • 装饰器简介
  • 装饰器推导流程
  • 装饰器模板
  • 装饰器语法糖

global与nonlocal

money = 666
def index():
    global money  #局部修改全局变量 需要使用关键字声明
    money = 123
index()
print(money)  # 123
'''
global 在局部名称空间直接修改全局名称空间的数据
'''
def index():
    name = 'jason'
    def inner():
        nonlocal name  #内部局部修改外部局部
        name = 'kevin'
    inner()
    print(name)  # name就是kevin 不加声明则name就是jason 把握函数定义原则函数在定义阶段就已经把名字的查找顺序固定死了
index()
'''
nonlocal 在内部名称空间修改局部名称空间中的数据
'''

name_list = ['jason', 'kevin']
def index():
    name_list.append('oscar')
index()
print(name_list)  # ['jason', 'kevin', 'oscar'] 当是可变类型使用了内置方法局部可以直接往全局列表里添加数据值

函数名的多种用法

函数其绑定的也是一块内存地址 只不过该地址里面存放的不是数据值而是一段代码 函数名加括号就会找到该代码并执行
# 用法1:函数名可以当做变量名赋值
def index():pass
res = index
res()  # 本质就是在调用index函数
# 用法2:函数名可以当做函数的参数
def index():
    print('from index')
def func(a):
    print(a)
    a()
func(index)  # 打印函数名index ——> <function index at 0x00000159E2A660D0>然后再打印from index
# 用法3:函数名可以当做函数的返回值
def index():
    print('from index')
def func():
    print('from func')
    return index
res = func()  # 先执行func()打印from func再返回index赋值给变量名res
print(res)  # 此时变量名res指的是index函数内存地址打印的是内存地址
res()  # 相当于index加括号调用函数index函数体代码

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
}
whie True:
    print('''
    1.注册功能
    2.登入功能
    3.提现功能
    4.转账功能
    5.购物功能
    ''')
    choice = input('请选择功能项>>>:').strip()
    # 判断用户输入的编号在不在字典的K中
    if choice in func_dict:
        # 根据键获取值(函数名)
        func_name = func_dict.get(choice)
        # 函数名加括号调用
        func_name
    else:
        print('功能编号不存在')
	# 下列代码的弊端在于功能较多时 代码过于复杂
    # if choice == '1':
    #    register()
    # elif choice == '2':
    #   login()
    # elif choice == '3':
    #   withdraw()
    # elif choice == '4':
    #    transfer()
    # elif choice == '5':
    #   shopping()
    # else:
    #   print('功能编号不存在')

闭包函数

'''
定义在函数内部的函数 并且用到了外部函数名称空间中的名字
	1.定义在函数内部
	2.用到外部函数名称空间中的名字
'''
def idex():
    name = 'jasn'
    def inner():
        print(name)

闭包函数实际应用>>>:是另一种给函数体代码传参的方式!!!

# 给函数体代码传参的方式1:代码里面缺什么变量名形参里面就补什么变量名
def register(name ,age):
    print(f'''
    姓名:{name}
    年龄:{18}
    ''')
register('jason', 18)
# 给函数体代码传参的第二种方式:闭包函数
def outer(name, age):
    # name = 'jason'
    # age = 18
    def register():
        print('''
        姓名:{name}
        年龄:{age}
        ''')
    return register
res = outer('jason', 18)  # outer函数调用name=jason age=18返回值是register函数名赋值给res变量名
res()  # res加括号相当于register加括号调用
res()  # 并且res加括号可以反复调用
res = outer('kevin', 28)
res()
res()

装饰器简介

1.概念
	什么叫装饰器?
    	在不改变被装饰对象原代码和调用方式的情况下给被装饰对象添加新的功能
2.本质
	并不是一门新的技术 而是由函数参数、名称空间、函数名多种用法、闭包函数组合到一起的结果
3.口诀
	对修改封闭 对扩展开放
4.储备知识
	时间相关操作
    import time
    print(time.time())  # 时间戳(距离1970-01-01零时零分所经历的秒数)
    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(1)
    print('from index')
def home():
    time.sleep(2)
    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.tiem()
    print('函数index的执行时间为:', end_time - start_time)
get_time()
'''3.函数体代码写死了 只能统计index的执行时间 如何才能做到统计更多的函数运行时间 直接传参变换统计的函数'''
def get_time(xxx):
    start_time = time.time()
    xxx()
    end_time = time.tiem()
    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)
l1 = 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')

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)
fucn2()
'''7.被装饰函数不知道有没有参数以及有几个参数 如何兼容'''
def func(a):
    time.sleep(o.1)
    print('from func', a)

def func1(a, b):
    time.sleep(0.2)
    print('from func1', a, b)
def ouet(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()
        res1 = xxx(*args, **kwargs)
        end_time = time.time()
        print('函数执行时间为:', end_time - start_time)
        return res1
    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):
        print('执行函数前可以添加的额外功能')
        res = func(*args, **kwags)  # 执行被装饰的函数
        print('执行函数之后可以添加的额外功能')
        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()

练习

# 编写一个用户认证装饰器
#   函数:register login transfer withdraw
#   基本要求
#    	 执行每个函数的时候必须先校验身份 eg: jason 123
#   拔高练习(有点难度)
#    	 执行被装饰的函数 只要有一次认证成功 那么后续的校验都通过
is_flag = False


def outer(func):
    def inner(*args, **kwargs):
        global is_flag
        if is_flag == False:
            user = input('校验用户>>>:').strip()
            pwd = input('校验密码>>>:').strip()
            if user == 'jason' and pwd == '123':
                is_flag = True
                res = func(*args, **kwargs)
                return res
        elif is_flag == True:
            res = func(*args, **kwargs)
            return res
    return inner


@outer
def register():
    while True:
        name = input('请注册您的用户名>>>:').strip()
        password = input('请创建您的密码>>>').strip()
        with open(r'z.txt', 'r', encoding='utf8') as read_f:
            for read_line in read_f:
                name1, pwd1 = read_line.split('|')
                if name1 == name:
                    print('用户已存在')
                    break
            else:
                with open(r'z.txt', 'a', encoding='utf8') as write_f:
                    write_f.write(f'{name}|{password}\n')
                return '注册成功'


@outer
def login():
    user_name = input('请输入您的用户名>>>:').strip()
    user_pwd = input('请输入您的密码>>>:').strip()
    with open(r'z.txt', 'r', encoding='utf8') as read_f:
        for line in read_f:
            real_name, real_pwd = line.split('|')
            if user_name == real_name and user_pwd == real_pwd.strip('\n'):
                return '登入成功'
        return '用户名或密码错误'


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



@outer
def withdraw():
    balance = 100
    while True:
        withdraw_money = int(input('请输入您要提现的金额>>>:'))
        if withdraw_money <= balance:
            print(f'提现成功 剩余余额{balance - withdraw_money}')
            return '提现成功'
        else:
            print(f'余额不足 {withdraw_money}提现不了')
            continue


func_dict = {'1': register, '2': login, '3': transfer, '4': withdraw}

while True:
    print('''
    1.注册功能
    2.登入功能
    3.转账功能
    4.提现功能
    ''')
    choice = input('请输入功能项>>>:').strip()
    if choice in func_dict:
        index = func_dict.get(choice)()
        print(index)
    else:
        print('无该功能项')
posted @   小福福  阅读(119)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
  1. 1 原来你也在这儿 温余福
  2. 2 世间美好和你环环扣扣 温余福
  3. 3 随风起舞 温余福
  4. 4 罪恶都市 温余福
随风起舞 - 温余福
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 米果

作曲 : 高橋優

编曲 : 刘胡轶/貢多杰

制作人 : 刘胡轶/吴青峰

配唱制作人 : 刘胡轶

乐器监制 : 刘胡轶

吉他 : 胡晨

贝斯 : 甯子达

弦乐录音棚 : 中国剧院录音棚

录音工程师 : 倪涵文/李游/李杨/邢铜/韩宽/李巍

录音监制 : 倪涵文/李游

混音&母带工作室 : OKmastering studio

混音&母带工程师 : 全相彦

制作协力 : 刘西洋

制作发行 : 智慧大狗 × 天才联盟

出品人 : 张葛

监制 : 崔恕/王明宇

弦乐监制 : 李朋

弦乐 : 国际首席爱乐乐团

鼓(打击乐):祁大为

和音编写&演唱:鱼椒盐

人声&吉他&鼓(打击乐)录音棚:55Tec studio

我曾将青春翻涌成她

我曾将青春翻涌成她

也曾指尖弹出盛夏

心之所动 且就随缘去吧

这一路上走走停停

这一路上走走停停

顺着少年漂流的痕迹

迈出车站的前一刻

竟有些犹豫

不禁笑这近乡情怯

不禁笑这近乡情怯

仍无可避免

而长野的天

依旧那么暖

风吹起了从前

从前初识这世间

从前初识这世间

万般流连

看着天边似在眼前

也甘愿赴汤蹈火去走它一遍

如今走过这世间

如今走过这世间

万般流连

翻过岁月不同侧脸

措不及防闯入你的笑颜

我曾难自拔于世界之大

我曾难自拔于世界之大

也沉溺于其中梦话

不得真假 不做挣扎 不惧笑话

我曾将青春翻涌成她

我曾将青春翻涌成她

也曾指尖弹出盛夏

心之所动 且就随缘去吧

逆着光行走 任风吹雨打

短短的路走走停停

短短的路走走停停

也有了几分的距离

不知抚摸的是故事 还是段心情

也许期待的不过是 与时间为敌

再次看到你

微凉晨光里

笑得很甜蜜

从前初识这世间

从前初识这世间

万般流连

看着天边似在眼前

也甘愿赴汤蹈火去走它一遍

如今走过这世间

如今走过这世间

万般流连

翻过岁月不同侧脸

措不及防闯入你的笑颜

我曾难自拔于世界之大

我曾难自拔于世界之大

也沉溺于其中梦话

不得真假 不做挣扎 不惧笑话

我曾将青春翻涌成她

我曾将青春翻涌成她

也曾指尖弹出盛夏

心之所动 且就随缘去吧

晚风吹起你鬓间的白发

晚风吹起你鬓间的白发

抚平回忆留下的疤

你的眼中 明暗交杂 一笑生花

我仍感叹于世界之大

我仍感叹于世界之大

也沉醉于儿时情话

不剩真假 不做挣扎 无谓笑话

我终将青春还给了她

连同指尖弹出的盛夏

心之所动 就随风去了

以爱之名 你还愿意吗

点击右上角即可分享
微信分享提示