Python用for / if转换和过滤列表



是否有一种方法可以在单个列表推导中同时进行转换和过滤,即:

def transform(el):
if some_condition(el):
return None
return complex_logic(el)
def main():
transformed = [transform(el) for el in some_list if transform(el) != None]

但避免调用transform两次?也就是说,把它赋值给一个变量,就像(在伪python中):

def main():
transformed = [transformed for el in some_list let transformed = transform(el) if transformed != None]

从Python 3.8开始可以使用海象操作符:=:

def main():
return [res for el in some_list if (res := transform(el)) is not None]

这样,调用transform函数的结果存储在res中,然后您可以在列表推导的表达式部分使用它。

let transformed = transform(el)替换为for transformed in [transform(el)]

我将从简单、习惯到可读的角度来解决这个问题:

使用temp变量的简单循环

简单但冗长的for循环可用于"cache"转换产生一个临时变量t:

def transform(el):
if some_condition(el):
return None
return complex_logic(el)

def main():
transformed_list = []
for el in some_list:
t = transform(el)  # invoked once
if t is not None:  # equivalent to `if transform(el) != None`
transformed_list.append(t)

嵌入式列表推导

就像Kelly Bundy建议的那样,嵌入列表推导式:

  1. 元素转换
  2. 非空
  3. 过滤器

参见列表推导式中的临时变量

变换的解耦条件

可以应用命令查询分离(CQS)

对程序有简化作用,使其状态(通过查询)和状态更改(通过命令)更易于理解。

假设两个给定的函数(some_conditioncomplex_logic)是单独定义的,因为每个函数都实现了单一职责(SRP)。那么利用这种分离并在合适的组合中重用这两个步骤将是重要的:

  1. 查询:由filter首先使用条件函数作为谓词
  2. 命令:之后通过复杂逻辑转换

这样,管道或流甚至可能变得更可读:

transformed = [complex_logic(el) for el in filter(some_condition, some_list)]

最后,这接近Samwise在他的评论中建议的:现在遵循SRP。

最新更新