返回None或元组并解压缩

Ste*_*ini 25 python return-value

我总是对这个事实感到恼火:

$ cat foo.py
def foo(flag):
    if flag:
        return (1,2)
    else:
        return None

first, second = foo(True)
first, second = foo(False)

$ python foo.py
Traceback (most recent call last):
  File "foo.py", line 8, in <module>
    first, second = foo(False)
TypeError: 'NoneType' object is not iterable
Run Code Online (Sandbox Code Playgroud)

事实是,为了正确解压而没有麻烦,我要么捕获TypeError,要么有类似的东西

values = foo(False)
if values is not None:
    first, second = values
Run Code Online (Sandbox Code Playgroud)

这有点烦人.有没有一个技巧可以改善这种情况(例如,在没有foo返回(无,无)的情况下将第一个和第二个设置为无)或关于像我提出的案例的最佳设计策略的建议?*变量可能吗?

Amb*_*ber 27

好吧,你可以做......

first,second = foo(True) or (None,None)
first,second = foo(False) or (None,None)
Run Code Online (Sandbox Code Playgroud)

但据我所知,没有更简单的方法来扩展None以填充整个元组.

  • 一般来说,我不喜欢这种语法,因为有意外的假Y值的危险,但在这种情况下它没关系. (3认同)

Unk*_*own 21

我没有看到返回有什么问题(无,无).它比这里建议的解决方案更清晰,这些解决方案涉及代码中的更多更改.

您希望None自动拆分为2个变量也没有意义.

  • +1 - 绝对 - 让函数返回如此混乱的结果并且必须在调用者中处理它是奇怪的. (2认同)
  • @Alex:嗯,这取决于.通常,您可以拥有应该返回_x_(x = what)的例程,如果没有找到则返回None.如果你知道x是一个元组,并且是两个对象的元组,那么这是一个特殊情况,但如果找不到_x_或None则仍然有效.解压缩它的事实对于被调用的例程是无视的. (2认同)

rob*_*rob 17

我认为存在抽象问题.

函数应该保持一定程度的抽象,这有助于降低代码的复杂性.
在这种情况下,要么函数不保持正确的抽象,要么调用者不尊重它.

功能可能是这样的get_point2d(); 在这种情况下,抽象级别在元组上,因此返回None将是发出某些特定情况(例如,不存在的实体)的好方法.在这种情况下的错误是期望两个项目,而实际上你唯一知道的是该函数返回一个对象(与2d点相关的信息).

但它也可能是这样的get_two_values_from_db(); 在这种情况下,抽象将通过返回None来打破,因为函数(顾名思义)应该返回两个值,而不是一个!

无论哪种方式,使用函数的主要目标 - 降低复杂性 - 至少部分地丢失了.

请注意,此问题不会与原始名称一起显示; 这也是为什么在功能和方法上给出好名字总是很重要的原因.


Ned*_*der 7

我认为没有诀窍.您可以将调用代码简化为:

values = foo(False)
if values:
    first, second = values
Run Code Online (Sandbox Code Playgroud)

甚至:

values = foo(False)
first, second = values or (first_default, second_default)
Run Code Online (Sandbox Code Playgroud)

其中first_default和second_default是您给第一个和第二个默认值的值.