有参装饰器知识补充、三元表达式,列表、字典、集合的生成式,匿名函数,匿名函数在内置函数中的使用
有参装饰器的补充知识
1.有参装饰器作用:当装饰器内部代码需要额外的数据,那么无法在原有的的两个函数形参中添加额外形参,这时考虑使用有参装饰器
2.最外层outer1形参能否写成outer1(*args,**kwargs)?
写没有问题,但是最外层填写的args与kwargs变量名与inner、func_name里面的可变长参数之间有冲突
解决方法:outer1(*a,**b),即使用其他变量名
3.在被修饰对象的函数有参数时,且装饰器内部需要单独使用某一个参数时,装饰器是否可以写成下面的方式:
def outer1(a,b,c):
def outer(func_name):
def inner(user_id,*args,**kwargs):
res = func_name(user_id,*args,**kwargs)
return res
return inner
return outer
@outer1(1,2,3)
def func(user_id,name,pwd):
pass
func(123,'nana',456)
ps:单独使用user_id其实时有两种方式:
第一种:func(123,'nana',456)实参123、'nana'、456传入形参中,组织成了元组(123,'nana',456)给args,当我们想取其中任意某个值得时候,直接用索引取值的方式即可
第二种:当我们想要获取func(123,'nana',456)实参中的123(user_id),可以直接在inner函数括号里面写user_id,*args,**kwargs和func_name函数的括号里写user_id,*args,**kwargs
三元表达式
1.三元表达式:使代码更加简洁,并且仅限于二选一的情况下使用,不建议嵌套使用
1.1 if else正常使用
name = 'nana'
pwd = 123
if name =='nana' and pwd ==123:
print("登陆成功")
else:
print("登陆失败")
1.2 三元表达式
name = 'nana'
pwd = 123
res = "登陆成功" if name =='nana' and pwd ==123 else "登陆失败"
print(res)
2.语法结构:符合条件的值1 if 条件 else 不符合条件的值2
3.在python中代码不是精简越少越好,在精简的过程中还要保证代码的可读性
eg :res = 123 if 10 > 5 else (222 if 0 else (666 if 1 == 2 else 666))
此时用三元表达式的嵌套,可读性不强
生成式
掌握列表生成式、字典生成式、集合生成式,元组没有元组生成式一说,在后面的迭代器知识中讲解
列表生成式
1.导入练习
name_list = ['jason', 'kevin', 'oscar', 'jerry', 'tony']
给上述列表中所有的数据值加上_NB的后缀
方式一:for循环后进行拼接操作,再添加到新列表中
list1 = []
for i in name_list:
res = i + '_NB'
list1.append(res)
print(list1) # ['jason_NB', 'kevin_NB', 'oscar_NB', 'jerry_NB', 'tony_NB']
方式二:列表生成器
list1 = [i+'_NB' for i in name_list]
print(list1) # ['jason_NB', 'kevin_NB', 'oscar_NB', 'jerry_NB', 'tony_NB']
2.原理 :列表生成器先执行for循环,然后将一个个取出的数据值给for前面的代码处理
3.在列表生成式中,for循环可以和if条件语句连用,先执行for循环,然后将一个个数据值交给if来进行判断,如果瞒住条件,就交给for前面的代码语句,如果不瞒住的话,就丢弃
ps:for、 if、 else三者之间不能同时存在,因为 else既可以和 for循环搭配使用,又可以和 if条件搭配使用,同时出现的话,会造成冲突
需求:给name_list列表中所有的数据值加上_NB的后缀 ,除了'tony'
代码:
name_list = ['jason', 'kevin', 'oscar', 'jerry', 'tony']
list1 = [i + '_NB' for i in name_list if i != 'tony']
print(list1) # ['jason_NB', 'kevin_NB', 'oscar_NB', 'jerry_NB']
字典生成式、集合生成式
字典和集合的生成式,其实和列表的生成式用法差不多,都是进行for循环依次值,有if条件的话,进行条件判断,结果为真,就传递给for前面的代码语句,结果为假,就舍弃;如果没有if条件判断,就直接将值传递个for前面的代码语句
1.字典生成器:不常用
dic1 = {i:'nana' for i in range(4) if i !=2}
print(dic1) # {0: 'nana', 1: 'nana', 3: 'nana'}
2.集合生成式
set1 = {i+1 for i in range(5) if i !=3}
print(set1) # {1, 2, 3, 5}
匿名函数
匿名函数简介
1.匿名函数就是没有函数名的函数
2.语法结构: lambda 形参:返回值
eg:
直接调用: (lambda x, y: x * y)(1, 2)
print((lambda x, y: x * y)(1, 2)) # 2
命名调用:res = lambda x, y: x * y
print(res) # <function <lambda> at 0x0000011AB2BF1E18>
print(res(1,2)) # 2
3.应用场景:匿名函数通常需要配合其他函数一起使用 用于减少代码
匿名函数在内置函数中的使用
max()、min()
1.max()内置函数:是在数字或字母(ASCII码对应得数据值)所在的容器里,最大的数值,min()求最小值
ps:内层相当于for循环,然后数值一一比对,所以不能够直接比较字典里的值,但可以定义一个函数与max()函数连用,为了使代码简洁,就导入了匿名函数与内置函数使用
2.练习
2.1 求列表中的最大值
l1 = [223, 3423, 123, 24, 34, 35, 435, 3, 24, 3534, 53, 24, 234, 132, 4234, 456, 456, 5345, 4, 234, 345, 23, 2123432]
方式一:
l2 = []
for i in l1:
if len(l2) == 0:
l2.append(i)
else:
if i > l2[0]:
l2[0] = i
else:
continue
print(l2[0]) # 2123432
方式二:
print(max(l1)) # 2123432
2.2 求字典里所对应的值的最大值
dic = {
'jason': 100,
'aj': 123,
'Bason': 9999999,
'zero': 888
}
ps:直接用max(dic) 返回的值是zero,它比较的是键中的字母所对应的ASCII码的数字大小,此时需要定义一个函数
def index(k):
return dic.get(k)
print(max(dic, key=index)) # Bason
为例使代码更加简洁,引入了匿名函数
print(max(dic, key=lambda k: dic.get(k))) # Bason
map()映射
1. map(function,iterable):将传入的函数依次作用到序列的每一个元素,并把结果作为新的Iterable返回 >>>iterable---一个或多个序列
ps:map()内置函数底层相当于对序列做了for循环,将序列的数值一一传入到函数中作为形参,然后返回的结果存放在新的序列中
2.练习
l1 = [11, 22, 33, 44, 55, 66]
需求:将列表中所有的数据值自增20
方式1:for循环
l2 =[]
for i in l1:
i += 20
l2.append(i)
print(l2) # [31, 42, 53, 64, 75, 86]
方式2:列表生成式
l2 = [i+20 for i in l1]
print(l2) # [31, 42, 53, 64, 75, 86]
方式3:map函数
def index(x):
return x+20
res = map(index,l1)
print(list(res)) # [31, 42, 53, 64, 75, 86]
为了简洁代码,用匿名函数:
res = map(lambda x:x+20,l1)
print(res) # <map object at 0x00000165F47FB2B0>
print(list(res)) # [31, 42, 53, 64, 75, 86]
filter()过滤
1.filter(function, iterable):用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象 iterable -- 可迭代对象
ps:filter()内置函数底层相当于对序列做了for循环,将序列的数值一一传入到函数中作为形参,然后返回满足条件的数据值,最后存放在新的序列中
2.练习
l1 = ['jason', 'kevin', 'oscar', 'tony']
需求:移除数据值里面的jason
方式1:for循环
l2 = []
for i in l1:
if i == 'jason':
continue
else:
l2.append(i)
print(l2) # ['kevin', 'oscar', 'tony']
方式2:列表生成式
l2 = [i for i in l1 if i != 'jason']
print(l2) # l2 = [i for i in l1 if i != 'jason']
方式3:filter()
def index(x):
return x != 'jason'
res = filter(index,l1)
print(res) # <filter object at 0x00000223E6AB7320>
print(list(res)) # ['kevin', 'oscar', 'tony']
为了简洁代码,用匿名函数:
res = filter(lambda x:x!='jason',l1)
print(res) # <filter object at 0x000002B7168674A8>
print(list(res)) # ['kevin', 'oscar', 'tony']
reduce()累积
1.reduce(function, sequence, initial=None):会对参数序列中元素进行累积(Python3.x中reduce()已经被移到functools模块里,如果我们要使用需要引入functools模块来调用reduce() 函数)
ps:reduce()内置函数底层相当于对序列做了for循环,将序列的数值第一次传入两个值到函数中作为形参,之后一个一个的传入作为形参,返回的结果是一个整体
2.练习
l2 = [1, 2, 3]
需求:求列表中所有数据值的和
方式1:for循环
sum = 0
for i in l2:
sum += i
print(sum) # 6
方式2:sum()
res = sum(l2)
print(res) # 6
方式3:reduce() 将很多单体 变成一个整体
from functools import reduce
def index(x,y):
return x+y
res = reduce(index,l2)
print(res) # 6
为了简洁代码,用匿名函数:
res = reduce(lambda x,y :x+y,l2)
print(res) # 6
zip()拉链
1.zip():将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。若传入参数的长度不等,则返回列表的长度和参数中长度最短的对象相同
2.练习
2.1 相同长度
l1 = ['name','pwd']
l2 = ['nana',123]
print(zip(l1, l2)) # <zip object at 0x000002780A6A3708>
res = zip(l1, l2)
print(list(res)) #[('name', 'nana'), ('pwd', 123)]
2.2 不同长度
l1 = [1,2,3,4,5,6]
l2= ['nana','xiao','lisa','linda']
l3 = [3,4,5,6,8]
res = zip(l1,l2,l3)
print(list(res)) # [(1, 'nana', 3), (2, 'xiao', 4), (3, 'lisa', 5), (4, 'linda', 6)]