- 转换并同时计算数据
- 问题:
- 需要在数据序列上执行聚集函数(比如 sum(),min(),max()),但首先需要转换或过滤数据。
- 解决方案:
- 一个非常优雅的凡是去结合数据计算与转换就是使用生成器表达式参数。比如:
nums = [1, 2, 3, 4, 5]
s = sum(x*x for x in nums)
print(s) # 55
- 下面是更多的例子:
import os
files = os.listdir("E:\\test\python_cookbook")
if any(name.endswith(".py") for name in files):
print("There be python!")
else:
print("sorry, no python")
# There be python!
portfolio =[{'name':'GOOG', 'shares': 50},
{'name':'YHOO', 'shares': 75},
{'name':'AOL', 'shares': 20},
{'name':'SCOX', 'shares': 65}
]
min_shares = min(s["shares"] for s in portfolio)
print(min_shares) # 20
- 讨论: 上面的示例演示了当生成器表达式作为一个单独参数传递给函数时候的语法,比如下面这些语法是等效 的。
s = sum((x*x for x in nums)) # 显示传递一个生成器表达式对象
s = sum(x*x for x in nums) # 省略了括号
- 使用一个生成器表达式作为参数会比创建一个历史列表更为高效和优雅。如果不使用生成器表达式的话:
nums = [1, 2, 3, 4, 5]
s = sum([x*x for x in nums])
-
这种方式同样可以到达想要的效果,但它会多一个步骤,先创建一个额外的列表。对于小型列表可能没什么关系, 但是如果元素数量非常大的时候,它会创建一个巨大的仅仅被使用一次就被丢弃的临时数据结构。而生成器表达 式方案会以迭代的方式装换数据,因此更省内存。
-
在使用一些聚集函数,比如 min() 和 max() 的时候,更倾向于使用生成器表达式,它接受一个 key 关键 字参数或许对你有很大帮助。比如,在上面的证劵例子中,你可能会考虑下面的版本:
min_shares = min(s["shares"] for s in portfolio)
print(min_shares)
min_shares = min(portfolio, key= lambda s: s["shares"])
print(min_shares)