python-列表推导式,迭代器和生成器,上下文管理器
python-列表推导式,迭代器和生成器,上下文管理器
- 一、列表推导式
- 1. 条件过滤
- 2. 嵌套循环
- 3. 条件表达式
- 字典推导式
- 集合推导式
- 二、迭代器
- 三、生成器
- 1. 生成器表达式
- 2. 生成器函数
- 四、上下文管理器
一、列表推导式
一种简洁、高效的创建列表的方式,允许在一行代码内生成列表,替代传统的 for 循环,实现简化代码
基本语法:[expression for item in iterable]
1. 条件过滤
[expression for
item in
iterable if condition
]
找出10以内的奇数
# for 循环
lst = []
for x in range(1, 11):if x % 2:lst.append(x)
print(lst) # [1, 3, 5, 7, 9]
# 列表推导式
lst = [x for x in range(1, 11) if x % 2]
print(lst) # [1, 3, 5, 7, 9]
# 10以内奇数的平方
lst = [x * x for x in range(1, 11) if x % 2]
打印30以内能被3整除的数
lst = [x for x in range(1, 31) if x % 3 == 0]
lst = [x for x in range(1, 31) if not x % 3]
print(lst) # [3, 6, 9, 12, 15, 18, 21, 24, 27, 30]
2. 嵌套循环
嵌套顺序与传统循环一致(从左到右对应外层到内层)
找出嵌套列表中包含字母 ‘m’ 的名字
# for 循环
names = [['tom', 'jerry', 'john'], ['jack', 'jerryxm', 'johnsdc']]
lst_name = []
for lst in names:for name in lst:if 'm' in name:lst_name.append(name)
print(lst_name) # ['tom', 'jerryxm']
# 嵌套循环遍历
print([name for lst in names for name in lst if 'm' in name])
3. 条件表达式
[expression_if_true if
condition else
expression_if_false for
item in
iterable]
过滤50以内能被3整除的数,如果这个数是奇数就返回0,偶数返回这个数本身
print([x if x % 2 == 0 else 0 for x in range(1, 51) if not x % 3])
# [0, 6, 0, 12, 0, 18, 0, 24, 0, 30, 0, 36, 0, 42, 0, 48]
字典推导式
键值互换
d1 = {'a': 1, 'b': 2}
d2 = {v: k for k, v in d1.items()}
print(d2) # {1: 'a', 2: 'b'}
将列表 lst 中的元素作为键,元素的索引作为值
lst = ['a', 'b', 'c']
d3 = {v: k for k, v in enumerate(lst)}
print(d3) # {'a': 0, 'b': 1, 'c': 2}
集合推导式
自动去重
lst = [-1, 1, 2, 1]
s1 = {i * i for i in lst}
print(s1) # {1, 4}lst1 = ['asdf', 'das', 'sdfasd', 'dsdfs']
将列表中长度大于3的字符串转化为大写,保存在新列表中
lst = [i.upper() for i in lst1 if len(i) > 3]
print(lst) # ['ASDF', 'SDFASD', 'DSDFS']
二、迭代器
实现了 __iter__
和 __next__
方法叫做迭代器
__next__方法 不断返回下一个值
__iter__方法 返回自身
str1 = "abc"
print(dir(str1)) # '__iter__'
iteror = str1.__iter__() # 得到迭代器# 判断是否为迭代器
print(dir(iteror)) # '__iter__','__next__'from collections.abc import Iterator
print(isinstance(iteror, Iterator)) # True# for循环遍历会调用__iter__方法得到一个迭代器,再调用迭代器的__next__方法,不断获取下一个值
# 直到遇到StopIteration终止
print(iteror.__next__()) # a
print(next(iteror)) # b
print(next(iteror)) # c
# print(next(iteror)) StopIteration
循环遍历1-9
lst = [1,2,3,4,5,6,7,8,9] # 一次性生成在内存里
for i in lst:print(i)
for i in range(1,10): # 懒加载print(i)
迭代器 --> 惰性求值,懒加载,节省内存空间
class NumIter(object):def __init__(self, n=0):self.n = ndef __iter__(self):return selfdef __next__(self):self.n += 1return self.nn1 = NumIter()
for i in n1:if i == 10:breakprint(i)
实现斐波那契数列的迭代器
class Fibonacci(object):def __init__(self):self.n1 = 1self.n2 = 1def __iter__(self):return selfdef __next__(self):num = self.n1self.n1, self.n2 = self.n2, self.n1 + self.n2return numn = Fibonacci()
# _ 是一个惯用的变量名,表示 “这个变量不重要,只是用于占位”
for _ in range(10):print(next(n), end=" ") # 1 1 2 3 5 8 13 21 34 55
三、生成器
是一种特殊的迭代器
不需要手写__iter__ 和 next 方法,实现迭代器更加优雅
生成器只有两种实现方式 生成器表达式、生成器函数
1. 生成器表达式
类似列表推导式,但用圆括号 ()
result = (x for x in range(10) if x % 3 == 0)
print(result) # <generator object <genexpr> at 0x000001561C115630>
print(dir(result)) # '__iter__','__next__'
2. 生成器函数
在函数体中,包含yield关键字
的函数就叫生成器函数
yield 保留中间算法,下次继续执行
def ger_content():x = 2yield xy = 3yield yz = 4yield zg = ger_content()
print(g, dir(g))
print(next(g)) # 2
print(next(g)) # 3
print(next(g)) # 4
# print(next(g)) # StopIteration
生成器函数,不断获取下一个值
def func1():count = 1while 1:yield countcount += 1g = func1()
print(next(g)) # 1
print(next(g)) # 2
实现斐波那契数列的生成器
def Fibonacci():n1 = 1n2 = 1while 1:yield n1n1, n2 = n2, n1 + n2n = Fibonacci()
for _ in range(10):print(next(n), end=" ") # 1 1 2 3 5 8 13 21 34 55
需要读取一个巨大的文件,或者一个巨大的数据集合的时候,可以使用生成器
def read(file_path, chunk_size=1024):with open(file_path, 'r', encoding='utf-8') as file:while True:# 读取指定大小的块chunk = file.read(chunk_size)# 如果读取到的内容为空,说明已经到文件末尾if not chunk:break# 使用yield返回读取到的块yield chunk
四、上下文管理器
实现__enter__
和__exit__
方法
完成资源分配、资源释放(文件打开关闭、数据库连接、
线程、进程、锁)
fp = open("a.txt") # 迭代器 上下文管理器
print(dir(fp)) # '__enter__', '__exit__', '__iter__','__new__'
自定义上下文管理器
class ContextManager:def __enter__(self):print("this is enter ...")return selfdef __exit__(self, exc_type, exc_val, exc_tb):print("this is exit ...")print(exc_type,exc_val,exc_tb) # None 无异常return True # 返回为真,就会终止异常def show(self):print("this is show ...")# 上下文管理器对象 使用with语句管理
with ContextManager() as ctx:print("使用对象")ctx.show()1/0
print("end ...")# this is enter ...
# 使用对象
# this is show ...
# this is exit ...
# <class 'ZeroDivisionError'> division by zero <traceback object at 0x000001D14DF25DC0>
# end ...