【问题标题】:Changing number of returned values depending on number of passed arguments [duplicate]根据传递的参数数量更改返回值的数量[重复]
【发布时间】:2018-08-28 15:30:12
【问题描述】:

是否有一种简短的方法可以对参数元组 *args 执行操作,如果将单个参数传递给函数,则返回单个参数,否则返回参数元组? 如下例所示。

def transform(*args):
    if len(args) == 1:
        return args[0] + 1
    else:
        return tuple(arg + 1 for arg in args)

这样对于单个参数,您可以简单地调用转换而无需额外的解包:

x = transform(3)

以及多个参数:

a, b, c = transform(1, 2, 3)

另一种选择是说总是接受 Sized 并返回 Sized,

def transform_2(args):
    return tuple(arg + 1 for arg in args)

但这似乎使用户代码不那么直观:

x, = transform_2((3,))
a, b, c = transform_2((1, 2, 3))

或者这个解决方案更好吗?

【问题讨论】:

  • 你不应该这样做。它打破了单一返回类型规则。 stackoverflow.com/questions/1839289/…
  • @FHTMitchell 我不认为它违反了这个规则,transform(3) 的输入类型是单个整数,transform(1, 2, 3) 的输入类型是三个整数的元组,我返回的是相同的对象类型。
  • @DikobrAz 您的函数没有单一的返回类型。它返回不同类型的值取决于参数的类型
  • 嗯,不完全是。如果你输入的是一个元组,那么它会写成transform((1, 2, 3))。在正式的类型系统中,(Int) -> T1(Int, Int?, Int?) -> T2 的超类型,因此T2 必须是T1 的子类型(这里我使用? 表示可选,而不是像Kotlin 中那样可以为空)。我同意,看起来像 (T) -> T 的函数是可以接受的。
  • 即使是(T) -> T 类型的函数也不是真正的单个函数;它是一整类函数的 架构,例如 (Int) -> Int(Char) -> Char 等。

标签: python python-3.x


【解决方案1】:

总是采用可迭代的 API 更容易理解,并且不会给用户带来很大的负担。

def transform(args):
    return tuple(arg + 1 for arg in args)

x = transform((3,))  # or transform([3])
a, b, c = transform([1,2,3])

如果您尝试传递一个字符串,任何尝试做您想做的事情都会失败,因为您可能打算 foo("123") 返回单个值,而不是 foo("1") 的结果、foo("2")foo("3"),但没有明确测试 str,您将无法区分字符串参数和另一个可迭代对象。

【讨论】:

  • 你能澄清一下吗?不清楚为什么它对用户更友好。
  • @asynts 这个问题从一个错误的前提开始。
  • @chepner 在我给 transform("123") 的示例中实际上正在做预期的事情 - 转换“123”而不是转换“1”、“2”和“3”。
  • @DikobrAz 是的,与只做一件事(修改可迭代对象的每个元素)并将其留给调用者以提供可迭代对象的函数相比,您的函数要复杂得多且难以测试和维护.
  • @chepner 我同意它更难维护,这就是为什么我要问这个问题,看看是否有更好的解决方案。但是用户需要编写的代码更少,而且看起来非常直观。此外,在您的示例中,如果用户不小心调用transform("123") 而不是transform(("123",)),那么它似乎不太容易出错,那么他将得到transform("1"), transform("2"), transform("3"),这是不希望的,我将无法检查这种情况并引发错误。跨度>
猜你喜欢
  • 2018-07-06
  • 2019-06-03
  • 2018-10-30
  • 2016-03-28
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多