【问题标题】:Making a complicated list comprehension conditional使复杂的列表理解成为条件
【发布时间】:2019-02-15 20:31:10
【问题描述】:

这是我目前的单行:

leader = [server.get_member(x) for x in self.rosters[server.id][clan]['members'] if discord.utils.get(server.get_member(x).roles, id="463226598351699968")]

我只想在server.get_member(x) 不是False 时运行它。如何将此额外逻辑添加到此列表理解中?我知道如何做一个基本的 for in 语句,但是嵌套得比这更深对我来说有点混乱。

【问题讨论】:

  • 请把它翻译成一个普通的for loop 以提高可读性,如果你是在可预见的未来必须维护它的人,为了你自己的利益
  • 你应该努力编写干净、可维护的代码,而不是将所有内容都塞进一个列表中
  • Python 列表推导对很多事情都很有用,但如果你开始迷失在逻辑中,可能是时候将其分解为常规循环了
  • 这是你的 API 还是其他人的 - 你能改进分解吗?如果没有任何成员,让server.get_member(x) 返回None 可能会更好。如果self.rosters[server.id][clan]['members']是你自己的代码,那么最好把它分解成更OO的东西。
  • 需要 for-loop/if-statements 而不是列表理解的一个强烈的代码味道是,您正在解决一个明确需要存储状态正如@blue_note 所说,通过两次调用server.get_member(x)

标签: python list-comprehension


【解决方案1】:

一般来说,不要为了写单行字而牺牲可读性。如果不是很明显如何通过列表理解来做到这一点,那么使用 for 循环。

leader = []

for x in self.rosters[server.id][clan]['members']:
    member = server.get_member(x)
    if member and discord.utils.get(member.roles, id="463226598351699968"):
        leader.append(member)

尽管在这种特定情况下,由于您不需要x,因此您可以在迭代时使用map 来应用server.get_member

leader = [m for m in map(server.get_member, self.rosters[server.id][clan]['members'])
          if m and discord.utils.get(m.roles, id="463226598351699968")]

【讨论】:

    【解决方案2】:

    你不能。列表理解中的项目无法保存,因此您必须对其进行两次评估。即使可以,不要。列表推导用于过滤,而不是作为副作用运行代码。它不可读且容易出错。

    【讨论】:

      【解决方案3】:

      一般情况下,您可以通过迭代 1 元组的嵌套列表推导来实现临时变量赋值的效果:

      leader = [m for x in self.rosters[server.id][clan]['members'] for m in (server.get_member(x),) if m and discord.utils.get(m.roles, id="463226598351699968")]
      

      但在这种特殊情况下,正如@OlivierMelançon 在评论中指出的那样,由于附加赋值只是将值映射到函数调用,因此您可以使用map 函数来实现所需的结果:

      leader = [m for m in map(server.get_member, self.rosters[server.id][clan]['members']) if m and discord.utils.get(m.roles, id="463226598351699968")]
      

      【讨论】:

        【解决方案4】:

        虽然我同意 cmets 的建议,但您不应该将其写成对可读性的理解,但您可以尝试:

        leader = [server.get_member(x) for x in self.rosters[server.id][clan]['members'] if discord.utils.get(server.get_member(x).roles, id="463226598351699968") if server.get_member(x)]
        

        类似于this 的回答。

        【讨论】:

        • 这会调用 server.get_member 3 次。
        • 是的,这绝对是一种非常糟糕的方式,当我输入它时,我很担心。
        猜你喜欢
        • 2022-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-29
        • 2021-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多