Safe dereferencing in Python
Question:
Groovy has a nice operator for safe dereferencing, which helps to avoid NullPointerExceptions:
variable?.method()
The method
will only be called, if variable
is not null
.
Is there a way to do the same in Python? Or do I have to write if variable: variable.method()
?
Answers:
Python has no such thing. This is because there is no null
pointer in Python. Well, there is the special None
value, which is often used in situations, where it represents “no value”. But that is just a convention. None
is a value/object like all others. And since there is no null
, there is no operator to deal with it.
EDIT 2021:
There is a new package that is sort of a hack featuring exactly this functionality in Python. Here is the repo: https://github.com/paaksing/nullsafe-python
from nullsafe import undefined, _
value = _(variable).method()
assert value is undefined
assert not value
assert value == None
Works with AttributeError
and KeyError
aswell
dic = {}
assert _(dic)["nah"] is undefined
assert _(dic).nah is undefined
The wrapped object typings will remain effective.
-
No, there isn’t.
-
But to check for None
, you don’t write if x:
, you write if x is None:
. This is an important distinction – x
evaluates to False
for quite a few values that are propably perfectly valid (most notably 0-equivalent numbers and empty collections), whereas x is None
only evaluates to True
if the reference x
points to the singleton object None
.
-
From personal experience, such an operator would be needed very rarely. Yes, None
is sometimes used to indicate no value. But somehow – maybe because idiomatic code returns null objects where sensible or throws exceptions to indicate critical failure – I only get an AttributeError: 'NoneType' object has no attribute '...'
twice a month.
-
I would argue that this might be a misfeature. null
has two meanings – "forgot to initialize" and "no data". The first is an error and should throw an exception. The second case usually requires more elaborate handling than "let’s just not call this method". When I ask the database/ORM for a UserProfile
, it’s not there and I get null
instead… do I want to silently skip the rest of the method? Or do I really want to (when in "library code") throw an approriate exception (so "the user (code)" knows the user isn’t there and can react… or ignore it) or (when I’m coding a specific feature) show a sensible message ("That user doesn’t exist, you can’t add it to your friend list") to the user?
An idiom I have seen and used is callable(func) and func(a, b, c)
in place of a plain function call (where the return value is not used). If you are trying to use the return value, however, this idiom will yield False
if the function is not callable, which may not be what you want. In this case you can use the ternary operator to supply a default value. For example, if the function would return a list that you would iterate over, you could use an empty list as a default value with func(a, b, c) if callable(func) else []
.
I’ve used this feature in Groovy, so I won’t repeat the blub paradox of other posters.
In Groovy a statement like this
if(possiblyNull?.value){
...
Does this in Python
try:
testVar = possiblyNull.value
except:
testVar = None
if(testVar):
It’s definitely a cool feature in Groovy, and is helpful in removing syntactical noise. There are a few other bits of syntactical sugar, like the Elvis operator or *, but they do sacrifice legibility as the expense for quick fix symbols (in other words, they’re no Pythonic).
Hope that helps 🙂
First of all, your options depend on what you’d like the expression to evaluate to if the variable is not dereferencable. I’ll assume None
is the appropriate result in these examples.
A common idiom for some circumstances in Python uses conditional expressions:
variable.method() if variable is not None else None
While this need may not be widespread, there are circumstances where it would be useful, especially when the references are nested and you would want something like this, where that idiom quickly gets cumbersome.
a?.b?.c?.d
Note that support for a ?.
operator for safe deferencing is one of the main topics of PEP 505: None-aware operators | Python.org. It’s current status is “deferred”.
Some discussion of it is at:
Let’s say you’re parsing xml, and you’re currently writing this:
element = root.find("name")
name = "unnamed" if element is None else name.text
Python 3.8 introduced an assignment expression (the walrus operator) and can now write this pretty elegantly:
name = "unnamed" if (name := root.find("name")) is None else name.text
Answering your question: yeah, you need to write if-esle clause, but use the pythonic way:
variable.method() if variable else None
Groovy has a nice operator for safe dereferencing, which helps to avoid NullPointerExceptions:
variable?.method()
The method
will only be called, if variable
is not null
.
Is there a way to do the same in Python? Or do I have to write if variable: variable.method()
?
Python has no such thing. This is because there is no null
pointer in Python. Well, there is the special None
value, which is often used in situations, where it represents “no value”. But that is just a convention. None
is a value/object like all others. And since there is no null
, there is no operator to deal with it.
EDIT 2021:
There is a new package that is sort of a hack featuring exactly this functionality in Python. Here is the repo: https://github.com/paaksing/nullsafe-python
from nullsafe import undefined, _
value = _(variable).method()
assert value is undefined
assert not value
assert value == None
Works with AttributeError
and KeyError
aswell
dic = {}
assert _(dic)["nah"] is undefined
assert _(dic).nah is undefined
The wrapped object typings will remain effective.
-
No, there isn’t.
-
But to check for
None
, you don’t writeif x:
, you writeif x is None:
. This is an important distinction –x
evaluates toFalse
for quite a few values that are propably perfectly valid (most notably 0-equivalent numbers and empty collections), whereasx is None
only evaluates toTrue
if the referencex
points to the singleton objectNone
. -
From personal experience, such an operator would be needed very rarely. Yes,
None
is sometimes used to indicate no value. But somehow – maybe because idiomatic code returns null objects where sensible or throws exceptions to indicate critical failure – I only get anAttributeError: 'NoneType' object has no attribute '...'
twice a month. -
I would argue that this might be a misfeature.
null
has two meanings – "forgot to initialize" and "no data". The first is an error and should throw an exception. The second case usually requires more elaborate handling than "let’s just not call this method". When I ask the database/ORM for aUserProfile
, it’s not there and I getnull
instead… do I want to silently skip the rest of the method? Or do I really want to (when in "library code") throw an approriate exception (so "the user (code)" knows the user isn’t there and can react… or ignore it) or (when I’m coding a specific feature) show a sensible message ("That user doesn’t exist, you can’t add it to your friend list") to the user?
An idiom I have seen and used is callable(func) and func(a, b, c)
in place of a plain function call (where the return value is not used). If you are trying to use the return value, however, this idiom will yield False
if the function is not callable, which may not be what you want. In this case you can use the ternary operator to supply a default value. For example, if the function would return a list that you would iterate over, you could use an empty list as a default value with func(a, b, c) if callable(func) else []
.
I’ve used this feature in Groovy, so I won’t repeat the blub paradox of other posters.
In Groovy a statement like this
if(possiblyNull?.value){
...
Does this in Python
try:
testVar = possiblyNull.value
except:
testVar = None
if(testVar):
It’s definitely a cool feature in Groovy, and is helpful in removing syntactical noise. There are a few other bits of syntactical sugar, like the Elvis operator or *, but they do sacrifice legibility as the expense for quick fix symbols (in other words, they’re no Pythonic).
Hope that helps 🙂
First of all, your options depend on what you’d like the expression to evaluate to if the variable is not dereferencable. I’ll assume None
is the appropriate result in these examples.
A common idiom for some circumstances in Python uses conditional expressions:
variable.method() if variable is not None else None
While this need may not be widespread, there are circumstances where it would be useful, especially when the references are nested and you would want something like this, where that idiom quickly gets cumbersome.
a?.b?.c?.d
Note that support for a ?.
operator for safe deferencing is one of the main topics of PEP 505: None-aware operators | Python.org. It’s current status is “deferred”.
Some discussion of it is at:
Let’s say you’re parsing xml, and you’re currently writing this:
element = root.find("name")
name = "unnamed" if element is None else name.text
Python 3.8 introduced an assignment expression (the walrus operator) and can now write this pretty elegantly:
name = "unnamed" if (name := root.find("name")) is None else name.text
Answering your question: yeah, you need to write if-esle clause, but use the pythonic way:
variable.method() if variable else None