Python 相当于 C# 6 中引入的 null 条件运算符

本文关键字:null 条件运算符 相当于 Python | 更新日期: 2023-09-27 17:56:13

Python 中是否有等效的 C# 空条件运算符?

System.Text.StringBuilder sb = null;
string s = sb?.ToString(); // No error

Python 相当于 C# 6 中引入的 null 条件运算符

怎么样:

s = sb and sb.ToString()

如果 sb 是 Falsy,则短路的布尔值停止,否则返回下一个表达式。

顺便说一句,如果得到 None 很重要...

sb = ""
#we wont proceed to sb.toString, but the OR will return None here...
s = (sb or None) and sb.toString()
print s, type(s)

输出:

None <type 'NoneType'>
<小时 />

过去有一些过于急切的评论删除,我想在这里复制作为警告:

评论者:你真的认为在Python中这样做是个好主意吗,Python是一种以代码可读性为荣的语言?

我:不,我没有。 这回答了这个问题 - 并说明了布尔短路的某些方面 - 但太"聪明"了一半。 如果您有理由使用此表单,请这样做,但请注意,乍一看其意图并不十分清楚。

PEP-505 下有一个提案,同时有一个库:

from pymaybe import maybe
print(maybe(None).toString())

那么,最简单的解决方案是:

result = None if obj is None else obj.method()

但是,如果您希望与 C# 的 Null 条件运算符具有相同的线程安全性的完全相同的等效项,则为:

obj = 'hello'
temp = obj
result = None if temp is None else temp.split()

代价是代码不是很漂亮;此外,还会向命名空间添加一个额外的名称temp

另一种方法是:

def getattr_safe(obj, attr):
    return None if obj is None else getattr(obj,attr)
obj = 'hello'
result = getattr_safe(obj,'split')()

在这里,权衡是调用开销的函数,但代码要清晰得多,尤其是在多次使用它时。

我用你要求的行为编写了这个函数。与链接and相比,这样做的一个优点是,当涉及到长链时,它更容易编写。请注意,这不适用于对象键,仅适用于属性。

def null_conditional(start, *chain):
    current = start
    for c in chain:
        current = getattr(current, c, None)
        if current is None:
            break
    return current

这是我运行的一些测试,以便您了解它是如何工作的

class A(object):
    b = None
    def __init__(self, v):
        self.b = v
class B(object):
    c = None
    def __init__(self, v):
        self.c = v    
a_1 = A(B(2))
a_2 = A(None)
print(null_conditional(a_1, 'b', 'c')) # 2
print(null_conditional(a_1, 'b', 'd')) # None
print(null_conditional(a_2, 'b', 'c')) # None
print(null_conditional(None, 'b')) # None
print(null_conditional(None, None)) # TypeError: attribute name must be string