Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python's equivalent to null-conditional operator introduced in C# 6

Tags:

python

c#

Is there an equivalent in Python to C# null-conditional operator?

System.Text.StringBuilder sb = null;
string s = sb?.ToString(); // No error
like image 870
Andrey Grachev Avatar asked Jul 09 '16 20:07

Andrey Grachev


People also ask

Does Python have a null coalescing operator?

It's a pity Python doesn't provide a None -coalescing operator. The ternary alternative is way more verbose and the or solution is simply not the same (as it handles all "falsy" values, not just None - that's not always what you'd want and can be more error-prone).

Does Python have a conditional operator?

The ternary operator is a way of writing conditional statements in Python. As the name ternary suggests, this Python operator consists of three operands. The ternary operator can be thought of as a simplified, one-line version of the if-else statement to test a condition.

How do you check for null in Python?

In Python, the 'null' object is the singleton None . To check if something is None , use the is identity operator: if foo is None: ...

What is the syntax for Python's conditional expression?

Conditional expressions (sometimes called a “ternary operator”) have the lowest priority of all Python operations. The expression x if C else y first evaluates the condition, C (not x); if C is true, x is evaluated and its value is returned; otherwise, y is evaluated and its value is returned.


4 Answers

How about:

s = sb and sb.ToString()

The short circuited Boolean stops if sb is Falsy, else returns the next expression.

Btw, if getting None is important...

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)

output:

None <type 'NoneType'>
like image 156
JL Peyret Avatar answered Oct 22 '22 10:10

JL Peyret


There's a proposal under PEP-505, in the meantime there's a library for this:

from pymaybe import maybe

print(maybe(None).toString())
like image 25
c z Avatar answered Oct 22 '22 10:10

c z


Well, the simplest solution would be:

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

But if you want the exact equivalent having the same thread safety as the C#'s Null-conditional operator, it would be:

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

The trade off is that the code isn't really pretty; Also an extra name temp gets added to the namespace.

Another way is:

def getattr_safe(obj, attr):
    return None if obj is None else getattr(obj,attr)

obj = 'hello'
result = getattr_safe(obj,'split')()

Here, trade-off is the function calling overhead, but much clearer code, especially if you are using it multiple times.

like image 31
Tanmay Avatar answered Oct 22 '22 10:10

Tanmay


I wrote this function with your required behavior. An advantage of this over chaining and is that it's easier to write when it comes to long chains. Heads up this doesn't work with object keys, only attributes.

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

Here's some tests I ran so you can see how it works

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
like image 40
Jad S Avatar answered Oct 22 '22 08:10

Jad S