推导式
推导式( comprehensions ),又称为解析式,是 Python 中的一种独有特性。推导式是可以从一个数据序列构建另一个新的数据序列的结构体。 共有三种推导式:
· 列表推导式
· 字典推导式
· 集合推导式
推导式具有固定的格式,下面以列表推导式为例(也适用于其他推导式):
variable = [out_exp_res for out_exp in input_list if out_exp == 2]
out_exp_res :列表生成元素表达式,可以是有返回值的函数。
for out_exp in input_list :迭代input_list将out_exp传入out_exp_res表达式中。
if out_exp == 2 : 根据条件过滤哪些值可以。
根据推导式的固定格式,下面分别给出三种数据类型的推导式实例。
列表推导式
1. 找出20以内的所有偶数
even_num = [i for i in range(20) if i % 2 == 0]
print(even_num) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
2. 找出10000以内的完全数的平方
完全数是所有真因子(除了它本身的所有约数)之和等于它本身的数。例如6, 1+2+3 = 6。 它的平方就是36。
def is_prefect_number(n):
cnt = 0
for i in range(1, n):
if n % i == 0:
cnt += i
if cnt == n:
return True
def squared(n):
return n * n
square_prefect_num = [squared(i) for i in range(1, 10000) if is_prefect_number(i)]
print(square_prefect_num) # [36, 784, 246016, 66064384]
3. 将名单的嵌套列表中含有两个 L(不区分大小写)的名字找出来
names = [['Smith', 'Johnson', ' Williams', 'Jones'], ['Brown', 'Allen',
'Lee', 'Hall'], ['Anderson', 'King', 'Collins', 'Miller', 'Taylor'], ['Phillips', 'Thompson']]
L_in_name = [name for lst in names for name in lst if name.lower().count('l') == 2]
print(L_in_name) # [' Williams', 'Allen', 'Hall', 'Collins', 'Miller', 'Phillips']
字典推导式
1. 将字典的 key 与 value 对调
dic = {'a': 1, 'b': 2}
dic_ver = {dic[k]: k for k in dic}
print(dic_ver) # {1: 'a', 2: 'b'}
2. 合并大小写对应的 value,并将 key 统一小写
dic = {'a': 3, 'b': 7, 'A': 9, 'c': 14, 'B': 1}
dic_merge = {k.lower(): dic.get(k.lower(), 0) + dic.get(k.upper(), 0) for k in dic}
print(dic_merge) # {'a': 12, 'b': 8, 'c': 14}
集合推导式
集合推导式就是列表推导式的 [] 改成 {} ,只是集合推导式自带去重效果。
1. 求列表中所有数的平方
set_square = {i**2 for i in [-2, -1, 1, 2, 3]}
print(set_square)
匿名函数
匿名函数是为了解决功能简单的需求而设计的一句话函数,在一些特定的情况下使用会更加简洁方便。
def squared(n):
return n**2
print(squared(2)) # 4
上面是常见的求一个数的平方的函数写法,我们把它换成匿名函数。
squared = lambda n: n**2
print(squared(4)) # 4
观察可得知匿名函数的固定格式为:
函数名 = lambda 参数: 返回值
注:
① 参数可以拥有多个,多个参数之间用逗号隔开;
② 匿名函数无论逻辑复杂程度都只能写一行,函数的返回值就是这一行的运行结果。 返回值可以是任意数据类型;
③ 匿名函数和普通函数一样可以通过 函数名(参数) 的方式调用。
通过上面的分析总结,我们知道匿名函数并不是真的匿名,它也是使用函数名来调用。 它的作用只是这样了吗? 这样它存在有什么意义呢? 我们直接用函数不就好了?
其实匿名函数大显身手的地方并不是这里,它在和其他功能函数合作的时候就可以真正的匿名了。例如配合 Python 中的内置函数使用:
1. 配合 map,将两个列表对应位置相加
ret = map(lambda x, y: x+y, [1, 3, 2, 7], [5, 9, 0, 1])
print(list(ret)) # [6, 12, 2, 8] ret是一个map对象,是一个迭代器,需要将它转化为列表
2. 使用 sorted,将字典按照 value 排序
dic = {'A': 2, 'B': 4, 'C': 1, 'D': 9, 'E': 7}
# 将字典转化为一个可迭代对象,每一个item就是一个的元祖,再按照元祖的第二个值(也就是字典的value)进行排序
list_dic = sorted(dic.items(), key=lambda item: item[1])
print(list_dic)
3. 现有两个元祖 ((‘a’), (‘b’)), ((‘c’), (d)),使用匿名函数将其转化为 [{‘a’:‘c’}, {‘b’:‘d’}]。
t1 = (('a'), ('b'))
t2 = (('c'), ('d'))
# 方法1
fuc = lambda x, y: [{i: j} for i, j in zip(x, y)]
print(fuc(t1, t2))
# 方法2
ret = list(map(lambda t: {t[0]: t[1]}, zip(t1, t2)))
print(ret)
# 方法3(不适用匿名函数,使用列表推导式)
ret = [{i: j} for i, j in zip(t1, t2)]
print(ret)
4. 有趣的刁钻小题
def multipliers():
return [lambda x:i*x for i in range(4)]
print([m(2) for m in multipliers()])
请问这段代码的运行结果是什么,怎么样才能得到我们想要的结果?
首先揭开谜底运行结果是[6, 6, 6, 6]
,为什么呢? 请看:
def multipliers():
return [lambda x:i*x for i in range(4)] # 1.列表推导式,这里面存放的是四个函数地址,函数为lambda x:i*x
# 2.那么实际上这里就是: return [lambda x: i*x的地址, lambda x: i*x的地址, lambda x: i*x的地址, lambda x: i*x的地址]
print([m(2) for m in multipliers()]) # 3.那么这里就变成了 for m in [lambda x: i*x的地址, lambda x: i*x的地址, lambda x: i*x的地址, lambda x: i*x的地址]
# 4.每一个m都是相同的函数名,传入参数2,这里就有了
# [lambda 2: i*2, lambda 2: i*2, lambda 2: i*2, lambda 2: i*2]
# 此时开始调用lambda函数,找到i的内存地址,发现i==3
那么我们想要结果为[0, 2, 4 6]
,该怎么做?
将函数中 return 的列表推导式改成生成器表达式就好了。