【问题标题】:Calling non-pure function in list comprehension在列表理解中调用非纯函数
【发布时间】:2019-03-23 05:52:19
【问题描述】:

我有以下代码(简化):

def send_issue(issue):
    message = bot.send_issue(issue)
    return message

def send_issues(issues):
    return [send_issue(issue) for issue in issues]

如您所见,send_issuessend_issue 是非纯函数。这被认为是在列表理解中调用非纯函数的好做法(和 Pythonic)吗?我想这样做的原因是这很方便。反对这样做的原因是,当您看到列表推导式时,您希望这段代码只生成列表,仅此而已,但事实并非如此。

更新: 我实际上想创建并返回与question相反的列表。

【问题讨论】:

  • 如果您不打算创建列表,我会反对。
  • 只要您实际上将生成的列表用作列表(这意味着您正在使用索引来检索生成列表的项目以进行进一步处理,我没有问题。如果如果您打算只迭代列表,请考虑将其设为生成器表达式而不是列表推导式。如果您根本不关心这些项目,那么您应该使用常规的 for 循环。
  • 我认为这没有任何问题。我说去吧;方法名称简单明了,这意味着如果我查看这段代码,我会很容易知道它的作用。
  • 从代码本身来看,send_issue 不是纯的并不明显。它是否发送消息返回已发送消息的内容?

标签: python list-comprehension side-effects pure-function


【解决方案1】:

这里的问题是 - 你真的需要创建列表吗?

如果是这样,那没关系,但不是最好的设计。
一个函数只做一件事是一种很好的做法,尤其是当它有像 I/O 这样的副作用时。
在您的情况下,该功能正在创建和发送消息。
要解决此问题,您可以创建一个发送消息的函数和一个生成消息的函数。

最好写成这样。

msgs = [bot.get_message(issue) for issue in issues]
for msg in msgs:
     bot.send(msg)

这更清晰,扩大了 API 的使用范围,同时保持了副作用的隔离。

如果你不想创建另一个函数,你至少可以使用map,因为它说 - “将此函数映射到每个元素”。

map(lambda issue: bot.send_issue(issue), issues) # returns a list

另外,函数send_issue 也不需要,因为它只是包装了bot.send_issue。 添加此类功能只会使代码变得嘈杂,这不是一个好习惯。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    • 2018-04-02
    • 1970-01-01
    • 2016-03-20
    • 1970-01-01
    • 2021-03-24
    • 1970-01-01
    相关资源
    最近更新 更多