【问题标题】:Python idiom for applying a function only when value is not None仅当 value 不是 None 时才应用函数的 Python 习惯用法
【发布时间】:2015-05-24 01:13:05
【问题描述】:

一个函数正在接收许多都是字符串但需要以各种方式解析的值,例如

vote_count = int(input_1)
score = float(input_2)
person = Person(input_3)

这一切都很好,除了输入也可以是None,在这种情况下,我不想解析值,而是将None分配给左侧。这可以通过

vote_count = int(input_1) if input_1 is not None else None
...

但这似乎不太可读,尤其是像这样的许多重复行。我正在考虑定义一个简化这一点的函数,比如

def whendefined(func, value):
    return func(value) if value is not None else None

可以像这样使用

vote_count = whendefined(int, input_1)
...

我的问题是,这有什么通用的成语吗?可能使用内置的 Python 函数?即使没有,这样的函数有常用的名称吗?

【问题讨论】:

  • 你已经拥有的 (whendefined) 在我看来很好。
  • 只是好奇 - 为什么 vote_count 是 None 比分配 0 更好?感觉后续代码中的 if 数量会更少。
  • 顺便说一句,由于您的输入始终是字符串,您可以将表达式缩短为 vote_count = int(input_1) if input_1 else None。 (如果input_ = "",这也会产生None
  • @thefourtheye 只是想知道标准库中是否有我错过的任何解决方案。另外我想知道是否有比whendefined 更好的名字。
  • @Nsh 有时需要显式建模缺失值。

标签: python nonetype


【解决方案1】:

在其他语言中有Option typing,它有点不同(解决了类型系统的问题),但具有相同的动机(如何处理空值)。

在 Python 中,更多地关注这类事情的运行时检测,因此您可以使用无检测保护(而不是 Option 类型所做的数据)包装函数。

您可以编写一个仅在参数不是 None 时才执行函数的装饰器:

def option(function):
    def wrapper(*args, **kwargs):
        if len(args) > 0 and args[0] is not None:
          return function(*args, **kwargs)
    return wrapper

您可能应该调整第三行以更适合您正在使用的数据类型。

使用中:

@option
def optionprint(inp):
    return inp + "!!"

>>> optionprint(None)
# Nothing

>>> optionprint("hello")
'hello!!'

并带有返回值

@option
def optioninc(input):
    return input + 1

>>> optioninc(None)
>>> # Nothing

>>> optioninc(100)
101

或者包装一个类型构造函数

>>> int_or_none = option(int)
>>> int_or_none(None)
# Nothing
>>> int_or_none(12)
12

【讨论】:

  • option(int)(input_1) 不是对whendefined(int, input_1) 的改进。 (请注意,我没有使用 option 作为装饰器,因为 OP 在他的 3 个示例中的 2 个上调用了内置函数。)
  • @StevenRumbalski 我同意,我喜欢 option 装饰器,但我认为它不会导致我的代码更具可读性。
  • 这是一个很好的观点,但我说的是在执行时创建一个包装器而不是链中的一个额外函数。在这样做时,它以更“静态”的方式声明意图。我认为定义int_or_none = option(int) 然后定义int_or_none(12) 是公平的。我认为这最终归结为风格。
  • @jonls 完全取决于您以及您想要变得多么明确。使用装饰器选项来定义您自己的函数将导致已知的函数始终将此装饰器作为其语义的一部分。将它用于内置类型会向我建议(根据我之前的评论)您声明一个新的类型构造函数,例如int_or_none。这可能是也可能不是非常非 Pythonic,但从其他语言的方向来看是有意义的。
  • @Joe 谢谢,这是有道理的。我认为您上次编辑中的代码与我的用例比其他两个示例更相关。
【解决方案2】:

如果您可以安全地将虚假值(例如 0 和空字符串)视为 None,则可以使用 boolean 和:

vote_count = input_1 and int(input_1)

因为看起来您正在接受字符串作为输入,所以这可能有效;无论如何,您都不能将空字符串转换为 int 或 float (或人)。虽然这个成语在 Lua 中常用。

【讨论】:

  • 这可能是一个可维护性的定时炸弹!今天它与字符串一起使用并且工作正常。在一年的时间里,它与数字一起使用,神秘的 0 被视为Nones。
  • @Joe 我不相信小脚本会有问题。
猜你喜欢
  • 2021-04-18
  • 1970-01-01
  • 1970-01-01
  • 2012-04-11
  • 1970-01-01
  • 1970-01-01
  • 2019-03-03
  • 1970-01-01
  • 2013-01-10
相关资源
最近更新 更多