昨日内容回顾
-
函数参数
""" 短的 简单的靠前 长的 复杂的靠后 同一个形参在调用的过程中不能多次赋值 """ 位置参数 位置形参 函数定义阶段括号内依次填写的变量名 位置实参 函数调用阶段括号内依次填写的数据值 基本规律是按照位置顺序一一对应传值 '''如果想打破位置顺序可以采用关键字传参''' 默认参数 默认形参 函数定义阶段就直接给形参赋值 不传则使用默认的,传了则使用传了的 可变长参数 可变长形参 * 接收多余的位置参数组织成元组赋值给符号后面的变量名 *args ** 接收多余的关键字参数组织成字典的形式赋值给符号后面的变量名 **kwargs 可变长实参 * 类似于for循环 将整个循环取值的整体结果 一次性传给函数 ** 将字典的键值对打散成关键字参数的形式 传给函数 命名关键字参数 在函数定义阶段在*args后面填写的默认参数 def index(name,age,*args,gender='male',**kwargs):pass
-
名称空间
用来存储变量名与数据值绑定的关系的地方(也可以直接看成是存变量名) 内置名称空间 解释器启动创建 结束销毁 全局名称空间 py文件运行创建 结束销毁 name = 'jason' if True: age = 18 while True: hobby = 'read' def index(): pass class MyClass(): pass 局部名称空间 函数体代码运行创建 结束销毁
-
名字的查找顺序
先判断自己在哪个名称空间 局部名称空间 >>> 全局名称空间 >>> 内置名称空间 局部名称空间相关事项 1.相互独立的局部名称空间无法彼此交互 2.局部名称空间嵌套 大致顺序是由内而外 ps:函数在定义阶段名字的查找顺序就已经固定死了 name = 'jason' def index(): name = 'kevin' def inner(): print(name) name = 'tony' inner() index() ps:名字的查找顺序可以打破 想怎么找就怎么找
今日内容概要
- global与nonlocal
- 函数名的多种用法
- 闭包函数
- 装饰器简介
- 无参装饰器
- 有参装饰器
- 装饰器模板
- 装饰器语法糖及修复技术
- 多层装饰器
今日内容详细
global与nonlocal
money = 666
def index():
global money
money = 123
index()
print(money)
"""
局部名称空间直接修改全局名称空间中的数据
"""
def index():
name = 'jason'
def inner():
nonlocal name
name = 'kevin'
inner()
print(name)
index()
'''
内层局部名称空间修改外层局部名称空间中的数据
'''
函数名的多种用法
函数名其实绑定的也是一块内存地址 只不过该地址里面存放的不是数据值而是一段代码 函数名加括号就会找到该代码并执行
1.可以当做变量名赋值
def index():pass
res = index
res()
2.可以当做函数的参数
def index():
print('from index')
def func(a):
print(a)
a()
func(index)
3.可以当做函数的返回值
def index():
print('from index')
def func():
print('from func')
return index
res = func()
print(res)
res()
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
}
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 choice == '1':
# register()
# elif choice == '2':
# login()
# elif choice == '3':
# withdraw()
# elif choice == '4':
# transfer()
# elif choice == '5':
# shopping()
# else:
# print('去你妹的 终于写完了')
闭包函数
"""
定义在函数内部的函数 并且用到了外部函数名称空间中的名字
1.定义在函数内容
2.用到外部函数名称空间中的名字
"""
def index():
name = 'jason'
def inner():
print(name)
闭包函数实际应用>>>:是另外一种给函数体代码传参的方式!!!
# 给函数体代码传参的方式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()
res()
res = outer('kevin', 28)
res()
res()
res()
装饰器简介
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)
装饰器推导流程
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()
作业
1.整理今日内容及博客
2.尽量搞懂装饰器推导流程
3.编写一个用户认证装饰器
函数:register login transfer withdraw
基本要求
执行每个函数的时候必须先校验身份 eg: jason 123
拔高练习(有点难度)
执行被装饰的函数 只要有一次认证成功 那么后续的校验都通过
提示:全局变量 记录当前用户是否认证
标签:第十二,index,outer,python,---,func,time,print,def
From: https://www.cnblogs.com/tengyifan888/p/16779200.html