今日内容回顾

  • 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('无该功能项')

global与nonlocal、函数名用法、闭包函数、装饰器的更多相关文章

  1. 函数名、闭包、装饰器 day11

    1, 函数名的内存地址,print(func) 2, 函数名可以赋值给其他变量 3, 函数名可以当做容器类的元素 4, 函数名可以当做函数的参数. 5, 函数名可以当做函数的返回值. 学名:第一对象 ...

  2. Day 11 函数名,闭包,装饰器. +作业

    '''一.函数名.def func(): print(5555)print(func)#输出结果 <function func at 0x026B5E88> 打印函数地址. # 1. 函数 ...

  3. python函数知识七 闭包、装饰器一(入门)、装饰器二(进阶)

    21.闭包 闭包:在嵌套函数内,使用非全局变量(且不使用本层变量) 闭包的作用:1.保证数据的安全性(纯洁度).2.装饰器使用 .__closure__判断是否是闭包 def func(): a = ...

  4. Python虚拟机函数机制之闭包和装饰器(七)

    函数中局部变量的访问 在完成了对函数参数的剖析后,我们再来看看,在Python中,函数的局部变量时如何实现的.前面提到过,函数参数也是一种局部变量.所以,其实局部变量的实现机制与函数参数的实现机制是完 ...

  5. Python函数进阶:闭包、装饰器、生成器、协程

    返回目录 本篇索引 (1)闭包 (2)装饰器 (3)生成器 (4)协程 (1)闭包 闭包(closure)是很多现代编程语言都有的特点,像C++.Java.JavaScript等都实现或部分实现了闭包 ...

  6. python函数作用域,闭包,装饰器

    第一:函数作用域: L:local 函数内部作用域 E:enclosing       函数内部与内嵌函数之间(闭包) G:global            全局作用域 B:build_in    ...

  7. python基础16_闭包_装饰器

    不了解是否其他语言也有类似 python 装饰器这样的东西. 最近才发现ECMAScript6也是有生成器函数的,也有 yield  generator 装饰器的基础知识是闭包: # 闭包:嵌套函数, ...

  8. Python高级--闭包与装饰器

    前言:在Python中,闭包是一种非常有用的功能!它通常与装饰器一起搭配使用,可以在不改变被装饰函数的功能的基础上,完成更多的功能.如权限认证. 一.如何定义闭包 1.闭包就是两个嵌套的函数,外层函数 ...

  9. Python—闭包和装饰器

    闭包 定义:内部函数对外部函数变量的引用,则将该函数与用到的变量称为闭包. 闭包必须满足以下三个条件: 必须有一个内嵌函数. 内嵌函数必须引用外部函数中的变量. 外部函数返回值必须是内嵌函数的引用. ...

  10. python_函数名的应用、闭包、装饰器

    0.动态传参内容补充: 0.1 单纯运行如下函数不会报错. def func1(*args,**kwargs): pass func1() 0.2 *的魔性用法 * 在函数定义的时候,代表聚合. *在 ...

随机推荐

  1. 密码学奇妙之旅、02 混合加密系统、AES、RSA标准、Golang代码

    CTR 计数器模式 计数器模式CTR是分组密码模式中的一种.通过将逐次累加的计数器进行加密来生成密钥流的流密码.每次加密时会生成一个不同的值来作为计数器的初始值. 可以事先进行加密.解密的准备. 加密 ...

  2. WPF绘制圆形调色盘

    本文使用writeableBitmap类和HSB.RGB模式来绘制圆形的调色盘. 开源项目地址:https://github.com/ZhiminWei/Palette RGB为可见光波段三个颜色通道 ...

  3. FEX-EMU Wine踩坑记录

    FEX是一个用于在ARM64平台运行X86软件的工具,比较成熟,但是网上资料很少,所以就写了这篇FEX运行Wine踩坑记录. Termux的Fex不能用(2022年5月) 要在debian系统安装fe ...

  4. 洛谷P1036 [NOIP2002 普及组] 选数 (搜索)

    n个数中选取k个数,判断这k个数的和是否为质数. 在dfs函数中的状态有:选了几个数,选的数的和,上一个选的数的位置: 试除法判断素数即可: 1 #include<bits/stdc++.h&g ...

  5. set 学习笔记

    一.声明 1.头文件 \(include<set>//包括set和multiset两个容器\) 2.声明 \(set<int> s\) s自带一个维度 二.迭代器 对" ...

  6. 深入浅出redis缓存应用

    0.1.索引 https://blog.waterflow.link/articles/1663169309611 1.只读缓存 只读缓存的流程是这样的: 当查询请求过来时,先从redis中查询数据, ...

  7. 如何实现一个SQL解析器

    ​作者:vivo 互联网搜索团队- Deng Jie 一.背景 随着技术的不断的发展,在大数据领域出现了越来越多的技术框架.而为了降低大数据的学习成本和难度,越来越多的大数据技术和应用开始支持SQL进 ...

  8. Selenium4.0+Python3系列(四) - 常见元素操作(含鼠标键盘事件)

    一.写在前面 上篇文章介绍的是关于浏览器的常见操作,接下来,我们将继续分享关于元素的常见操作,建议收藏.转发! 二.元素的状态 在操作元素之前,我们需要了解元素的常见状态. 1.常见元素状态判断,傻傻 ...

  9. SQL Server-表结构的操作

    1.修改表的字段的数据类型 alter table [File_Info] alter column Upload_Request_ID nvarchar(14) not null 2.添加表的字段并 ...

  10. SQL server 操作相关

    1.更改列的顺序后进行保存. 在SQL Server Management Studio中, "工具"--"选项"--"Designers" ...