是否有C#null-coalescing运算符的Python等价物?

Is there a Python equivalent of the C# null-coalescing operator?

在C中,有一个空合并运算符(写为??),允许在分配期间轻松(短)检查空值:

1
2
string s = null;
var other = s ??"some default value";

是否有与python等效的?

我知道我能做到:

1
2
s = None
other = s if s else"some default value"

但是有没有一个更短的方法(我不需要重复s)?


1
other = s or"some default value"

好的,必须澄清or操作符是如何工作的。它是一个布尔运算符,因此它在布尔上下文中工作。如果这些值不是布尔值,则出于运算符的目的将它们转换为布尔值。

注意,or运算符不只返回TrueFalse。相反,如果第一个操作数的计算结果为真,则返回第一个操作数;如果第一个操作数的计算结果为假,则返回第二个操作数。

在这种情况下,表达式x or y返回x,如果它是True或在转换为布尔值时计算为真。否则返回y。在大多数情况下,这将用于C?'s空合并运算符,但请记住:

1
2
3
4
5
42    or"something"    # returns 42
0     or"something"    # returns"something"
None  or"something"    # returns"something"
False or"something"    # returns"something"
""    or"something"    # returns"something"

如果您使用变量s来保存某个引用类实例或None的对象(只要您的类没有定义成员__nonzero__()__len__(),那么使用与空合并运算符相同的语义是安全的。

事实上,使用Python的这种副作用甚至可能很有用。由于您知道哪些值的计算结果为假,因此可以使用它来触发默认值,而无需特别使用None(例如,错误对象)。

在某些语言中,这种行为称为ELVIS运算符。


严格地说,

1
other = s if s is not None else"default value"

否则,s=false将成为"默认值",这可能不是预期值。

如果你想把这个改短,试试看

1
2
3
4
5
6
7
def notNone(s,d):
    if s is None:
        return d
    else:
        return s

other = notNone(s,"default value")


下面是一个函数,它将返回第一个不是none的参数:

1
2
3
4
5
def coalesce(*arg):
  return reduce(lambda x, y: x if x is not None else y, arg)

# Prints"banana"
print coalesce(None,"banana","phone", None)

reduce()可能不必要地迭代所有参数,即使第一个参数不是none,因此您也可以使用此版本:

1
2
3
4
5
def coalesce(*arg):
  for el in arg:
    if el is not None:
      return el
  return None


我知道答案是肯定的,但在处理对象时还有另一个选择。

如果您的对象可能是:

1
2
3
4
5
6
{
   name: {
      first:"John",
      last:"Doe"
   }
}

你可以使用:

1
obj.get(property_name, value_if_null)

像:

1
obj.get("name", {}).get("first","Name is missing")

通过添加{}作为默认值,如果缺少"name",则返回一个空对象并传递给下一个get。这类似于C_中的零安全导航,类似于obj?.name?.first


除了朱利亚诺关于"或"行为的回答之外:它是"快"的

1
2
>>> 1 or 5/0
1

所以有时候它可能是一些有用的捷径

1
object = getCachedVersion() or getFromDB()


我发现下面的两个函数在处理许多可变测试用例时非常有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
def nz(value, none_value, strict=True):
    ''' This function is named after an old VBA function. It returns a default
        value if the passed in value is None. If strict is False it will
        treat an empty string as None as well.

        example:
        x = None
        nz(x,"hello")
        -->"hello"
        nz(x,"")
        -->""
        y =""  
        nz(y,"hello")
        -->""
        nz(y,"hello", False)
        -->"hello" '''


    if value is None and strict:
        return_val = none_value
    elif strict and value is not None:
        return_val = value
    elif not strict and not is_not_null(value):
        return_val = none_value
    else:
        return_val = value
    return return_val

def is_not_null(value):
    ''' test for None and empty string '''
    return value is not None and len(str(value)) > 0