Python之推导式、迭代器与生成器

目录

  • python推导式
      • 列表推导式
      • 字典推导式
      • 集合推导式
  • 迭代器
      • \_\_iter__()
      • \_\_next__()
      • 自定义迭代器
      • 懒加载
  • 生成器
      • 生成器表达式
      • 生成器函数
        • send()方法、close()方法
        • yeild from
      • 应用
  • 小结


python推导式

推导式(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

迭代器

__iter__()

实现了该方法的即为可迭代对象,该方法会返回一个迭代器

哪些是可迭代对象?

容器:str、dict、list、set、tuple

range、打开的文件、socket等

__next__()

实现了该方法和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

send()方法、close()方法

通过下面的例子来理解

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()		# 关闭生成器,不能再使用

yeild from

精简语法,后面必须接可迭代对象

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

小结

可迭代对象、迭代器与生成器的关系
Python之推导式、迭代器与生成器_第1张图片

你可能感兴趣的:(python,python,开发语言)