能否在Python列表推导式中直接使用kwargs参数?
能否在Python列表推导式中直接使用kwargs参数?
我在优化旧函数时产生了疑问:是否可以在Python列表推导式中直接使用kwargs参数?
比如我有这样的数据集:
data = {"channels": [ {"channel_id": 1, "group_id": 1, "description": "First", "default_msg": "Hi!", "status": True}, {"channel_id": 2, "group_id": 1, "description": "Second", "default_msg": "Hi!", "status": True}, {"channel_id": 3, "group_id": 1, "description": "Third", "default_msg": "Hi!", "status": False}, {"channel_id": 4, "group_id": 2, "description": "Fourth", "default_msg": "Hi!", "status": True}, {"channel_id": 5, "group_id": 2, "description": "Fifth", "default_msg": "Hi!", "status": False}, ]}
我能轻松写出这样的单条件过滤函数:
def get_by_groups(group): return [c for c in data["channels"] if c["group_id"] == group]
但我好奇能不能通过接收kwargs作为多条件查询参数,直接在列表推导式里完成过滤。我找了相关示例但没找到可行方案。
我知道可以通过遍历kwargs键值对实现多条件过滤(不过下面这个写法是错误的,因为kwargs.keys()返回的是字典键视图对象,不能直接作为字典索引使用):
def get_channels(**kwargs): return [c for c in data["channels"] if c[kwargs.keys()] == kwargs.values()]
补充说明
我并不觉得下面的循环实现有问题,纯粹是出于好奇想知道能不能用列表推导式一步完成:
def get_channels(**kwargs) -> list: lst_groups = data["channels"] for key, value in kwargs.items(): lst_groups = [c for c in lst_groups if c[key] == value] return lst_groups
其实是可以在列表推导式里直接用kwargs实现多条件过滤的,核心是要检查每个频道字典是否匹配kwargs里的所有键值对。可以用all()结合生成器表达式来实现:
方案1(兼容键不存在的情况)
如果不确定传入的kwargs键是否都存在于频道字典中,用get()方法避免KeyError:
def get_channels(**kwargs): return [c for c in data["channels"] if all(c.get(key) == value for key, value in kwargs.items())]
方案2(确定键都存在时使用)
如果能保证所有传入的kwargs键都存在于频道字典里,直接用索引更高效:
def get_channels(**kwargs): return [c for c in data["channels"] if all(c[key] == value for key, value in kwargs.items())]
原理说明
all()函数会逐一检查生成器表达式中的每个条件,只有当kwargs里的每一组键值对都和频道字典对应键的值匹配时,才会将该频道加入结果列表。这种写法和你之前的循环过滤逻辑完全等价,但更紧凑,完全在列表推导式内完成了多条件过滤。
比如调用get_channels(group_id=1, status=True),会返回group_id为1且status为True的两个频道字典。
内容的提问来源于stack exchange,提问作者Guilherme Richter
相关产品推荐
相关产品推荐

