Python函数之多种缩减代码行方法
三元表达式
严格讲,python并没有其他语言中三元表达式,不过有类似的实现方法,即通过if语句配合else来模拟实现。
- 三元表达式可减少代码行数。
- 三元表达式仅限于二选一的情况并且不建议嵌套使用
# 三元表达式语法结构
值1 if 条件 else 值2
'''
如果if后面的条件成立 则使用if前面的值
如果if后面的条件不成立 则使用else后面的值
'''
各种生成式
- 生成式的语法结构基本相同
- 针对元组没有所谓的生成式一说
列表生成式
例:给列表中所有的数据值加上_DDD的后缀
name_list = ['kwan', 'kevin', 'oscar', 'jerry', 'tony']
''' 常规操作 '''
# 1.定义一个新的列表
new_list = []
# 2.循环原列表中所有的数据值
for name in name_list:
# 3.拼接_DDD后缀
new_name = name + '_DDD'
# 4.追加到新列表中
new_list.append(new_name)
print(new_list)
使用列表生成式则可以减少代码行数:
name_list = ['kwan', 'kevin', 'oscar', 'jerry', 'tony']
"""一行代码解决: 列表生成式"""
new_list = [name + '_DDD' for name in name_list] # 先执行for循环,然后将一个个的数据值交给for循环前面处理
print(new_list)
列表生成式还可以先执行 if 判断,再继续操作
name_list = ['kwan', 'kevin', 'oscar', 'jerry', 'tony']
new_list = [name + '_DDD' for name in name_list if name != 'kwan'] #先执行for循环,然后将一个个的数据值交给if判断,结果为True则最后交给for循环前面处理
print(new_list) # ['kevin_DDD', 'oscar_DDD', 'jerry_DDD', 'tony_DDD']
列表生成式中只能出现 for 和 if ,出现else编译器无法配对则会报错(if...else...,for...else...)
字典生成式
new_dict = {i: 'kwan' for i in range(3)} # 先执行for循环,然后将一个个的数据值交给for循环前面处理
print(new_dict) # {0: 'kwan', 1: 'kwan', 2: 'kwan'}
''' 先执行 if 判断,再继续操作 '''
new_dict = {i: 'kwan' for i in range(10) if i == 5} # 先执行for循环,当 i == 5 的 时候 i 的值为 kwan
print(new_dict) # {5: 'kwan'}
集合生成式
new_set = {i for i in range(10) if i == 6}
print(new_set) # {6}
匿名函数
Python 使用 lambda 来创建匿名函数
所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
- lambda 只是一个表达式,函数体比 def 简单很多。
- lambda 的主体是一个表达式,而不是一个代码块。仅仅能在 lambda 表达式中封装有限的逻辑进去。
- lambda 函数可接受任意数量的参数,但只能有一个表达式。
- lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
# lambda 函数的语法结构
lambda 形参: 返回值
例:一个 lambda 函数,它把作为参数传入的数字加 10,然后打印结果:
>>> x = lambda a : a + 10 # 命名调用
>>> print(x(5))
15
>>> (lambda a : a + 10)(5) # 直接调用
15
lambda 函数可接受任意数量的参数:
# 参数 a 与参数 b 相乘
x = lambda a, b : a * b
print(x(5, 6))
将匿名函数封装在一个函数内,这样可以使用同样的代码来创建多个匿名函数
# 将匿名函数封装在 myfunc 函数中
>>> def myfunc(n):
... return lambda a: a * n
...
>>> mydoubler = myfunc(2) # 给 myfunc 函数传入 2
>>> print(mydoubler(11))
22
>>> mytripler = myfunc(3) # 给 myfunc 函数传入 3
>>> print(mytripler(11))
33
匿名集合内置函数使用
匿名函数通常都需要配合其他函数一起使用,用于减少代码
常用内置函数
-
min()
求最小值
-
max()
求最大值
''' max ()函数返回可迭代的最大项或两个或多个参数的最大项,返回的是可迭代对象中的最大元素 '''
l1 = [223, 3423, 123, 24, 34, 35, 435, 3, 24, 3534, 53, 24, 234, 132, 4234, 456, 456, 5345, 4, 234, 345, 23, 2123432]
res = max(l1)
print(res) # 2123432
与lambda一起使用:
# 求value最大的key
>>> dic = {
... 'kwan': 10045,
... 'aj': 123,
... 'lili': 9999999,
... 'zero': 888
... }
# 惯性思维
>>> res = max(dic)
>>> print(res)
zero
'''
由于max()底层相当于用的是for循环,而字典在参与for循环时是key参与循环
即 'kwan' 'aj' 'lili' 'zero' 在比较大小
z = 122 为最大
'''
# print('A' > 'a')
# A-Z 65-90
# a-z 97-122
# 正确操作1
# 使用lambda函数
>>> res = max(dic, key=lambda k: dic.get(k)) # k为形参,dic.get(k)为返回值
>>> print(res)
lili
'''
max()中 'key='可以传入函数
字典传入lambda函数,字典的键(key)传到形参k,返回dic.get(k)字典的值(value)
则比较的是字典的值的大小
由于一开始for循环的是字典的key,所以结果会输出字典最大value的key lili
'''
# 正确操作2
# 不使用lambda函数
>>> def index(k): # 只能传一个值,否则报错
... return dic.get(k)
...
# max() for循环的是字典的key,所以这里传入index()的实参只有一个值
res = max(dic, key=index)
print(res) # lili
重要内置函数
- map()
# 需求:将列表中所有的数据值自增20
l1 = [11, 22, 33, 44, 55, 66]
# 方式1:for循环
l2 = []
for i in l1:
l2.append(i+20)
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()
res = map(lambda x: x + 20, l1)
print(res) # <map object at 0x000001954B581100>
print(list(res)) # [31, 42, 53, 64, 75, 86]
'''
map()底层用的也是for循环,会将l1里的数据值一个个循环出来
l1循环出来的数据值会传给lambda()处理,返回 x+20
map()会获取返回值
'''
# 不使用lambda(),只使用map()
def index(a):
return a + 20
res = map(index, l1)
print(list(res)) # [31, 42, 53, 64, 75, 86]
- filter()
# 需求:移除数据值里面的jason
l1 = ['jason', 'kevin', 'oscar', 'tony']
# 方式1:for循环
l2 = []
for i in l1:
if i != 'jason':
l2.append(i)
print(l2) # ['kevin', 'oscar', 'tony']
# 方式2:列表生成式
l2 = [i for i in l1 if i != 'jason']
print(l2) # ['kevin', 'oscar', 'tony']
# 方式3:filter()
res = filter(lambda a: a != 'jason', l1)
print(res) # <filter object at 0x00000195F21E6C70>
print(list(res)) # ['kevin', 'oscar', 'tony']
# 不使用lambda()自定义函数,只使用filter()
def index(a):
return a != 'jason'
res = filter(index, l1)
print(list(res))
- reduce()
# 需求:求列表中所有数据值的和
l2 = [1, 2, 3]
# 方式1:for循环
count = 0
for i in l2:
count += i
print(count) # 6
# 方式2:sum()
res = sum(l2)
print(res)
# 方式3:reduce() 将很多单体 变成一个整体
from functools import reduce
res = reduce(lambda x, y: x + y, l2, 100)
print(res) # 106
'''
reduce()底层先把实参前两个数据值传入lambda()的形参x,并将返回值作为下一次循环的参数之一
reduce()第二个参数可以指定一个值和前一个参数的返回值相加
'''
- zip()
n1 = [1, 2, 3]
n2 = ['jason', 'kevin', 'oscar']
res = zip(n1, n2)
print(res) # <zip object at 0x000002A9E38C7F40>
print(list(res)) # [(1, 'jason'), (2, 'kevin'), (3, 'oscar')
# eg2
n1 = [1, 2, 3, 4]
n2 = [5, 6, 7, 8]
n3 = 'jack'
res = zip(n1, n2, n3)
print(list(res)) # [(1, 5, 'j'), (2, 6, 'a'), (3, 7, 'c'), (4, 8, 'k')]
# eg3
n1 = [1, 2, 3, 4, 5, 6, 7]
n2 = [5, 6, 7, 8]
n3 = 'jason'
res = zip(n1, n2, n3)
print(list(res)) # [(1, 5, 'j'), (2, 6, 'a'), (3, 7, 's'), (4, 8, 'o')]
作业
# 将多层装饰器及有参装饰器的执行流程用文字具体描述出来
多层装饰器
装饰器即在不改变被装饰对象源代码和调用方式的情况下,为被装饰对象添加功能的工具
多层装饰器即在原来装饰器的基础上再叠加多个,叠加多个装饰器并无特殊之处
语法糖功能为自动将下面紧挨着的函数名当做参数传递给@符号后面的函数调用
多层装饰器有多个语法糖装饰函数名,从最靠近函数名的语法糖开始执行,即从下往上执行,最后一个语法糖才会做重命名操作
按照语法糖执行顺序一层层执行装饰器内的代码,第一层执行后返回第二层的函数名,第二层执行后返回第三层函数名,依此类推,最后作用到被装饰函数身上
有参装饰器
装饰器的参数都有其特定的功能,不能用来接收其他参数
给函数体代码传值有两种方式,一个是通过形参传值,另一个是闭包函数
有参装饰器即为在装饰器的外部再包一层函数,用来专门接收额外的参数,便于此函数内其他函数来引用参数
在语法糖中传入一个参数,装饰器外层的函数就可以获取到这个参数,在这个函数内的其他函数可以相应的使用这个参数,最终作用到被装饰函数

浙公网安备 33010602011771号