推导式(comprehensions)又称解析式,是Python的一种独有特性。推导式是可以从一个数据序列构建另一个新的数据序列的结构体。 共有三种推导,在Python2和3中都有支持:列表推导式、字典推导式、集合推导式
用[]生成list
基本格式: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: 根据条件过滤哪些值
# 列表推导式
# 30以内被3整除的数
print([i for i in range(0,30) if not i % 3])
# ⭐推导式嵌套,找出嵌套列表中包含两个‘e’的字符串
names = [[……],[……]]
print([i for lst in names for i in lst if i.count('e')==2])
# ⭐推导式叠加
# 求(x,y)其中x是0-5之间的偶数,y是0-5之间的奇数组成的元组列表
print([(x,y) for x in [0,1,2,3,4,5] if x%2==0 for y in range(0,6) if y%2!=0])
#字典推导式
d1={"a":1,"b":2}
d2={v:k for k,v in d1.items()}
print(d2)
自动去重
#集合推导式,跟列表推导式用法一样
#自带去重功能
lst=[-1,1,2,1]
s1 = { i*i for i in lst }
print(s1)
练习
#练习
# 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
q1 = ['a','ab','abc','abcd','abcde']
print([i.upper() for i in q1 if len(i) >=3])
# 求(x,y)其中x是0-5之间的偶数,y是0-5之间的奇数组成的元组列表
print([(x,y) for x in [0,1,2,3,4,5] if x%2==0 for y in range(0,6) if y%2!=0])
# 快速更换key和value # 期望结果:{10:'a', 34:'b'}
q3 = {'a': 10,'b': 34}
print({v:k for k,v in q3.items()})
# 合并大小写对应的value值,将k统一成小写 #期望 结果:{'a':5,'b':9,'c':3}
q4 = {'B':3,'a':1,'b':6,'c':3,'A':4}
print({k.lower():q4.get(k.lower(),0)+q4.get(k.upper(),0) for k in q4}) # 只遍历key
实现了该方法的即为可迭代对象,该方法会返回一个迭代器
哪些是可迭代对象?
容器:str、dict、list、set、tuple
range、打开的文件、socket等
实现了该方法和iter方法的即为迭代器,next()会返回一个值,在迭代器中的iter()方法则返回自身
通过不停调用迭代器的next()方法即可获取到可迭代对象的每一个值,超出范围后会报StopIteration错误
class NewIter():
def __init__(self):
self.num = 0
def __iter__(self):
return self
def __next__(self):
self.num += 1
return self.num
a = NewIter()
for i in a:
if i == 10:
break
print(i)
迭代器最大的特性————懒加载、惰性求值、需要的时候再生成
lst = [1,2,3,4,5,6] # 直接生成,存放在内存中,运行起来更快
for i in range(1,7) # 使用时再生成,更节省内存
是一种特殊的迭代器,是迭代器更优雅的写法
生成器只有两个写法,一种生成器表达式,一种叫做生成器函数
同样是惰性求值
result = ( x for x in range(1,31) if not x % 3 )
print(result) # ,返回一个生成器
print(dir(result)) # 实现了iter和next方法
for i in result:
print(i)
包含了yield关键字的函数,就叫做生成器函数
def get_content():
X=2
yield x
y=3
yield y
Z=4
yield z
g = get_content()
print(g) # 是一个生成器,同样实现了iter和next方法
print(next(g)) # 第一次执行next方法,遇到yield就退出,并且返回yield携带的参数,还会记录当前执行到的位置
print(next(g)) # 下一次执行next方法,则从上一次yield位置开始执行到下一个yield位置,以后的next方法也是如此
# 没有yield可返回时报StopIteration错误
示例:
def function1():
count = 1
while 1:
yield count
count += 1
f = function()
print(next(f)) # 从1开始输出
print(next(f)) # 每次加1
通过下面的例子来理解
def counter(start_at=5):
count = start_at
while True:
val = ( yield count ) # 正常情况yield不会返回值,val为None,而send方法可以返回值给生成器
print("val is:", val)
if val is not None:
count = val
else:
count += 1
count = counter(6)
print(next(count)) # 输出:6
print(next(count)) # 输出:7
count.send(100) # 输出:100 ,send方法可以改变中间存储的结果,并且会执行一次next()
print(next(count)) # 输出:101
count.close() # 关闭生成器,不能再使用
精简语法,后面必须接可迭代对象
def g1():
yeild from range(10) # 相当于下面的for循环
# for i in range(10):
# yield i
生成器读取大文件
def read_file(path):
SIZE = 655350
with open(path,"rb") as fp:
while True:
block = fp.read(SIZE)
if block: # 每次读取SIZE大小的文本,直到block为空时退出
yield block
else:
return
read = read_file("big_file.txt")
for i in read:
pass
------------
with open("big_file.txt") as fp: # 这是一行一行读的例子,运行速度上会慢很多
for i in fp:
pass