Python中的列表推导式和生成器表达式 (List Comprehension & Generator Expressions)
列表(list)是pthon中最常用的数据结构之一,有序,可变。
1.生成一个列表最原始的方法
def is_leap(year: int):
return year%4 == 0 and (year%100 != 0 or year%400 == 0)
Leap_Year_List = [] #空列表 或者用 Leap_Year_List = list()
for item in range(1582, 2022):
if is_leap(item):
Leap_Year_List.append(item) #通过append方法填充列表元素
2.列表推导式(List Comprehension)
当然,还有其他的方法来生成列表,用列表推导式我们可以将上面的代码简化至一行:
Leap_Year_List =[item for item in range(1582, 2022) if is_leap(item)] #通过for循环和if条件生成列表
note1: range()函数本身返回的也是整数列表
note2: 列表推导式里可以用多个for循环,返回的则是笛卡尔积
3.生成器表达式( Generator Expressions)
我们把列表表达式的[]换成()就得到了一个新的返回对象:生成器。
Leap_Year_Generator = (item for item in range(1582, 2022) if is_leap(item)) #得到生成器的这个方法称之为生成器表达式
所以,推导式和生成器类型不一样(一个是数据结构,一个是某种函数)导致它们的适用场景有所不同。生成含大量元素的列表会占用极大的内存空间,这种场景下一边循环一边计算效率更高。比如计算1到1,000,000,000的平方和,我们并不需要先得到一百万个元素的列表再求和,可以直接用生成器表达式来求和:
total = sum(num * num for num in range(1, 1000000000))
当列表是我们最终需要的结果时,用列表推导式;当列表只是我们运算的中间过程时,用生成器表达式。
note1: 生成器是一种特殊的迭代器。它的本质是一个能不断产生值的函数,它的意义在于提供了一种更为节省内存的方式去得到可迭代对象。
note2: 如果一个函数里有yield, 那它就是生成器。
note3: 迭代器是类,里面有数据成员(可迭代对象中的元素),有方法(iteration(),next())
4.拓展
举个生成器的例子:读取文本文件获得版本号
def get_version():
with open("version.txt", "r") as fi:
result = next(it for it in fi if it.startswith("__version__")) #生成器表达式
# txt中内容为 __version__ = "1.0.1"
return result.split('"')[1] #结果为1.0.1
另一个例子:读取文本文件返回列表
def get_install_list():
with open("sw_list.txt", "r") as fi:
lines = fi.readlines()
#txt中为多行内容
return [line.strip("\n") for line in lines if line] #列表推导式