【问题标题】:Multiple if/elif statements in a Python list comprehensionPython 列表推导中的多个 if/elif 语句
【发布时间】:2020-05-28 01:55:52
【问题描述】:

所以我是 Python 新手,需要一些时间来适应的一个概念是列表理解。我已经读到,如果使用得当,它们可以提高计算速度,而且如果你要以正确的方式学习 Python,它们是非常了解的。

我正在编写一个程序来实现粒子聚合算法,该算法涉及将多达 10^6 个粒子累积到一个不断增长的集群中。我将回顾我的代码以尽可能优化性能,并且我有以下功能:

 def step_all_walkers(walkers): 
    updated_positions = []
    for walker in walkers: 
        decision = random.randint(1,4)
        if decision == 1: 
            updated_walker = (min(walker[0]+1, N-1), walker[1])
        elif decision == 2: 
            updated_walker = (max(walker[0]-1, 1), walker[1])
        elif decision == 3: 
            updated_walker = (walker[0], min(walker[1] + 1, N-1))
        elif decision == 4: 
            updated_walker = (walker[0], max(walker[1]-1, 1))

        updated_positions.append(updated_walker)

    return updated_positions 

此函数使每个粒子(或我在代码中称其为 walker)在随机方向上走一个单位长度的步长,并防止粒子离开 N x N 网格。我注意到我正在创建并返回一个新列表updated_positions,并且由于这个列表和输入walker 列表可能非常大,我对列表推导的了解告诉我这可能是使用一个列表的好时机.然而,在这个问题的其他一些帖子中,只有一个 if/else 需要评估,人们回答说只使用一种好的 ole 时尚 for 循环。

那么我有几个问题:

1) 可以在列表推导中完成多个 if/elif 语句吗?

2) 把这个 for 循环写成列表理解有意义吗?这样做有什么好处吗?

我问这个问题的主要目的是建立更多的直觉,了解何时适合列表推导,以及看看这个函数是否可以提高效率。

【问题讨论】:

  • 1.可以链接多个 if-表达式,但在我看来这看起来很难看。 2. 列表推导也创建了一个新列表。所以你不会在这里获得清晰和效率。
  • 列表推导式也会生成一个新列表,所以我认为那里没有什么好处。对于内存大小,我什至不会担心几个 10^6 整数/整数元组的列表。你上面的代码很清楚。如果您想尝试列表推导,您可以创建一个覆盖案例并返回新位置并在列表推导中调用该函数的“移动”函数,但我认为您不会获得任何性能提升。
  • 您可以使用函数字典来选择更新函数,然后您可以将列表理解编写如下:return [update_map[randint(1,4)](walker) for walker in walkers]

标签: python list-comprehension


【解决方案1】:

我会把它变成一个查找字典开始,然后你可以考虑一个列表理解

decisions = {1: lambda walker: (min(walker[0]+1, N-1), walker[1])}
return [decisions[random.randint(1,4)](walker) for walker in walkers]

【讨论】:

  • 这不能回答任何 OP 的问题。
  • @Georgy - 我部分同意,第一个问题询问是否可以在列表理解中完成多个 if else - 是的,但没有任何必要,而且它也不会很容易阅读.第二个问题部分基于意见,部分示例太小,无法讨论优势
【解决方案2】:

list comprehensions should not be used 的情况是逻辑过于复杂。

For 循环更简单,因为它们允许:

  • 包括 cmets 来解释代码。
  • 使用控制流关键字,如继续。
  • 调试部分更容易使用日志语句或断言。
  • 让其他人通过逐行扫描轻松了解逻辑的复杂性

但是,正如 Sayse 所建议的,我们通常可以使用额外的数据结构和辅助函数来简化逻辑,以实现列表理解。

没有 if/else 语句的列表理解(需要绕过逻辑)

def step_all_walkers(walkers, N):
  def decision(walker):
    " Helper function for making a decisions "
    # Place decision choices into a data structure
    options = [
      lambda walker: (min(walker[0]+1, N-1), walker[1]),
      lambda walker: (max(walker[0]-1, 1), walker[1]),
      lambda walker: (walker[0], min(walker[1] + 1, N-1)),
      lambda walker: (walker[0], max(walker[1]-1, 1))]

    while True:
      n = random.randint(0, 3)  # use rather than (1, 4) to 
                                # provide proper index into options
      yield options[n](walker)

# Now, list comprehension is straight forward to follow
return [decision(walker) for walker in walkers]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-08
    • 2022-11-23
    • 2020-10-28
    • 2015-01-16
    相关资源
    最近更新 更多