学习python第五周学习总结
第四周学习总结
函数重要参数
*
与**
在实参中的作用
*
相当于是for循环拿到它后面的数据类型里面所有的值然后一次性传给函数
**
只适用于字典,将字典里的键值对把它变为关键字的参数传给函数
命名关键字参数
需要形参再传实参的时候 必须按照关键字参数才可以
在形参*args的后面 在**kwargs 的前面
名称空间
1.概念:
用来存放变量名与数据值之间绑定的地方
2.名称空间的分类:
2.1.内置名称空间:python解释器运行就会立刻创建的空间
存活周期:解释器运行时创建关闭时销毁
2.2.全局名称空间:py文件运行代码过程中产生的名字都会存入该空间
存活周期:py文件运行时创建结束时销毁
2.3.局部名称空间:函数体代码运行过程中产生的名字都会存入该空间
存活周期:函数体代码运行时创建结束时销毁
3.名字查找顺序:
查找名字之前先看自己在那个空间
查找顺序:局部--->全局--->内置,从里向外找不能打乱顺序,不能倒着找,只能按这个顺序
4.作用域与查找:
内置名称空间:在程序的任意位置都可以使用
全局名称空间:在程序的任意位置使用
局部名称空间:只能在各自的局部空间使用
5.global与nonlocal关键字:
如果使用了global这个关键字的时候,就意味着在局部空间出现的名字不再是新创建的,而是用的全局里出现的那个。
局部修改全局名称空间中不可变类型的数据,需要使用关键字global声明
在局部名称空间里修改局部名称空间里的数据值使用nonlocal
6.函数名的多种用法:
6.1.函数名可以被用来多次赋值
6.2.函数名可以被当作函数的实参
6.3.函数名可以被当作函数的返回值
6.4.函数可以被当作容器类型里面的数据值,通过取值取到加括号就可以使用
7.多功能函数模板
def add_user():
pass
def update_user_info():
pass
def target_user():
pass
def target_alluser():
pass
def delete_user():
pass
data_dict = {
'1':add_user,
'2':update_user_info,
'3':target_user,
'4':target_alluser,
'5':delete_user
}
while True:
print('''
1.添加员工信息
2.修改员工薪资
3.查看指定员工
4.查看所有员工
5.删除员工数据
''')
func_choice = input('请输入你选择的功能:')
# 运用的是成员变量来判断是否存在
if func_choice in data_dict:
# 通过K值取到V值,此时V值是一个函数名
func_name = data_dict.get(func_choice)
# 调用这个函数
func_name()
else:
print('没有这个功能')
闭包函数
1.定义:
定义在函数内部的函数并且内部函数使用了外部函数名称空间中的名字
2.实际应用:
在全局中使用局部空间里的名字
3.注意的点:
如果内层函数使用的名字是外层函数的形参,那么此时外层函数执行的过程就不是函数的形参与实参动态绑定动态解除了,它的等到内层函数执行结束后它才能结束
4.给函数体代码传值的方式:
4.1.通过形参传值
4.2.通过闭包函数
装饰器
定义:
在不改变被装饰对象原来调用的方式和内部代码的情况下给它增加功能
装饰器过程推导:
同一块代码在不同地方重复使用--->解决方式:封装成函数
多个不同的函数需要使用,函数体代码里参数写死了--->解决方式:给函数体添加形参
不同形参个数的函数无法兼容统计--->解决方式:*
args与**
kwargs,没有办法实现,通过闭包函数实现传参
但是改变了原来的调用方式,--->解决方式:外层套一层函数
装饰器初级版本:
def index():
pass
def outer(被装饰的函数的函数名):
def inner():
print('执行被装饰对象之前可以做的操作')
res = func()
print('执行被装饰对象之后可以做的操作')
return res
return 内部函数名
index = outer(index)
index()
home = outer(home)
home()
装饰器优化版本
def index():
pass
def outer(被装饰的函数的函数名):
def inner(*args, **kwargs):
print('执行被装饰对象之前可以做的操作')
res = func(*args, **kwargs)
print('执行被装饰对象之后可以做的操作')
return res
return 内部函数名
def home():
pass
index = outer(index)
index('iason')
home = outer(home)
home()
装饰器最终版本
from functools import wraps
def outer(func_name):
# 装饰器修复技术
@wraps(func_name) # 是为了让装饰器不容易被别人发现,做到真正的以假乱真,不会影响代码,写不写都可以
def inner(*args, **kwargs):
print('执行被装饰对象之前可以做的额外操作')
res = func_name(*args, **kwargs)
print('执行被装饰对象之后可以做的额外操作')
return res
return inner
# 装饰器语法糖
@outer # 相当于这个,index = outer(index)
def index():
pass
多层装饰器执行流程
多层装饰器的时候从最下面开始向上执行先执行语法糖根据语法糖与函数名的触发条件,将外层的函数从上至下一个一个的执行到最后回归到最开始的真正的函数名(并非真正的函数名是跟真正的函数名名字一样)的时候,再开始用上至下执行内部的函数,最终回归到要执行的那个函数,打印输出结果。
有参装饰器
1.在外部函数里加入形参,那么就得在语法糖里加入参数,但是如果在语法糖里加入了参数,那解释器自动识别函数名加()执行优先级,那么语法糖就不会执行了,外部函数括号里只能用来接收被装饰的函数名
2.在内部函数里加入形参,那么在执行内部函数的时候就得必须传入一个参数,但是传入了参数就不符合装饰器的原则了原本函数执行的时候是不需要传入参数的,可是现在需要,因此这种方法也不能
3.所以只能使用闭包函数解决,在最外面套一个函数,将需要传入的参数设置为形参,返回值为原外层函数,然后这个时候里面就是一个完整的装饰器,没有破坏它,同时这个额外新增的函数是可以传入多个值的
递归函数
原则上一层比一层简单,并且必须要有结束条件
递归:一层层向下找答案
回溯:根据已知条件去推结果
算法之二分法
对半平分与目标数字进行比较,目标数字大的话就在后半截,目标数字小的话就在前半截,然后再进行对半分比较大小,缺点是如果目标函数在首部或者尾部的时候采用二分法找的话效率会低,它必须是有序数列
三元表达式
特点:可以减少代码的行数
语法结构:条件为真时的结果 if 条件 else 条件为假时的结果
限制:仅限于二选一的情况并且不建议嵌套使用
各种生成式
1.列表生成式:
l1 = ['aa', 'bb', 'cc', 'dd', 'ee']
new_list = [name + '_nb' for name in l1]
print(new_list) # ['aa_nb', 'bb_nb', 'cc_nb', 'dd_nb', 'ee_nb']
2.字典生成式
d1 = ['aa', 'bb', 'cc', 'dd', 'ee']
new_dict = {i:'jason' for i in range(5)}
print(new_dict) # {0: 'jason', 1: 'jason', 2: 'jason', 3: 'jason', 4: 'jason'}
3.集合生成式
new_set = {i for i in range(10)}
print(new_set) # {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
new_set = {i for i in range(10) if i == 6}
print(new_set) # {6}
4.匿名函数结合其他内置函数使用
# 常见内置函数
# 1.max()----求最大值
d1 = {'zz': 199, 'ss': 67, 'dd': 3456, 'xx': 12345}
res = max(d1, key=lambda k: d1.get(k))
print(res) # xx
'''
# max底层是for循环,如果没有后面的key值,拿到的是k键,然后就是直接进行比较,通常的话是字符串,然后字符串比较通常是那第一位,通过编码进行比较大小的,如果有key值,for循环拿到的是k值,然后k值作为参数传给lambda中的参数,然后返回值通过get方法去得到v值,此时返回值就是v值,然后拿着v值进行比较,最后输出的是名字,是因为原来for循环出来的是k值,最终结果还是按照for循环来的
'''
# 如果匿名函数不可以用,那就使用函数
def index(k):
return d1.get(k)
res = max(d1,key=index)
print(res) # xx
'''需要注意的是index只能有一个形参,因为max底层是一个for循环一次只能拿一个值'''
# # 2.min()----求最小值
匿名函数
1.可以理解为没有函数名的函数
2.表达式:lambda 参数:return 返回值
匿名函数可以看作是一个表达式,只是它必须要有返回值而已
3.优点:可以省去定义函数的过程,结合一些内置函数使用,可以变为有名函数,减少代码,是代码更加简洁
重要内置函数
# 1.map()----映射
l1 = [1, 2, 3, 4, 6, 8, 10, 35, 67, 34, 76, 90, 15, 38, 29]
res = map(lambda x: x + 20, l1)
print(list(res)) # [21, 22, 23, 24, 26, 28, 30, 55, 87, 54, 96, 110, 35, 58, 49]
'''
# 底层用的是for循环,挨个将列表中的值取出来,每次取出来的函数交给函数的形参,然后传给返回值得出结果
'''
# 自定义函数
def index(a):
return a + 20
res = map(index, l1)
print(list(res))
# 2.filter()----过滤掉不符合条件的元素,返回符合条件的元素
l1 = [1, 2, 3, 4, 6, 8, 10, 29]
res = filter(lambda a: a != 3, l1)
print(list(res)) # [1, 2, 4, 6, 8, 10, 29]
# 3.reduce()---它与map()不同的是它需要传入俩个值
from functools import reduce
l2 = [1,4,5,7]
res_l2 = reduce(lambda x, y: x + y,l2,100)
print(res_l2) # 17
'''
# 将很多单体变成一个整体,一次性要给予俩个参数,第一次取值是需要俩个值,之后就是取一个了,其中另一个是上一次的返回值,后面还可以传值进去,就是在列表里的执行完后面又加上这个值
'''
# 4.zip()
n1 = [1,2,3]
n2 = ['jason','kevin','oscar']
res = zip(n1,n2)
print(list(res)) # [(1, 'jason'), (2, 'kevin'), (3, 'oscar')]
'''
# 可以拼接多个值,拼接的值要支持for循环,如果存放的数据长短不一,那就按照最短的那个来连接
'''
考试题
power = [] # 权限,登入后赋值
user_data = {
'1': {'name': 'jason', 'pwd': '123', 'access': ['1', '2', '3']},
'2': {'name': 'kevin', 'pwd': '321', 'access': ['1', '2']},
'3': {'name': 'oscar', 'pwd': '222', 'access': ['1']}
}
# 装饰器
def oout(number):
def outfun(func):
def inner(*args, **kwargs):
global power # 定义全局变量
if power:
if number in power:
func(*args, **kwargs)
else:
print('你没有权限')
else:
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
print(username,password,end=' ')
for value in user_data.values(): # 循环字典的value值
print(value.get('name'),value.get('pwd'),end=' ')
if username == value.get('name') and password == value.get('pwd'):
func(*args, **kwargs)
power = value.get("access")
print(f'当前权限为:{value.get("access")}')
if power:
if number in power:
func(*args, **kwargs)
else:
print('你没有权限')
break
else:
print('用户名或密码错误') # 全部循环完后
return inner
return outfun
@oout(number='1')
def func1():
print('from func1')
@oout(number='2')
def func2():
print('from func2')
@oout(number='3')
def func3():
print('from func3')
# 方法字典,加括号就可以调用
fun_dict = {
'1': func1,
'2': func2,
'3': func3,
}
while True:
number = input('请输入你要执行函数的编号(1,2,3): ').strip()
if number in fun_dict:
fun_dict.get(number)() # 用get方法取,报错时程序不会停止,加括号调用对应函数
else:
print('编号不存在')