43

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()?

tim_yates
  • 167,322
  • 27
  • 342
  • 338
deamon
  • 89,107
  • 111
  • 320
  • 448
  • 3
    @deamon: first of all i don't know Groovy and i don't want to argue about what i don't know but this feature (after i read about it now) seem no useful to me (and i may be wrong and most of the time i'm) because even if i do something like this __variable.?method()__ yes sure if variable is NULL it's not raising an Error but how do i know that the method was called , because it look to me like a silence error (actually i never needed something like this before) and if if i do something like this __a = variable.?method()__ so after i should do __if(a)__ so ... , did i miss something :) – mouad Oct 31 '10 at 21:16
  • 1
    I agree with singularity; I don't see how this could be all that useful. It looks like something you would sprinkle over your code to hide errors. – adw Oct 31 '10 at 21:36
  • @Seth Johnson: can you be more specific, did i say something wrong and if it's about my English is it that bad ? it's not my first language :) – mouad Oct 31 '10 at 21:39
  • I also agree with singularity. This has absolutely no real benefit and silently hides errors. I would much rather my program crash at that point then produce odd, hard to track down errors after the real problem occurred. – Ed S. Oct 31 '10 at 22:17
  • 13
    @all this is really useful when dereferencing properties, so: `addressbook?.people?.'tim_yates'?.age` would return a value if none of the properties in the chain were `null` or `null` if one of them is – tim_yates Nov 01 '10 at 10:11
  • 1
    @tim_yates: And then what do you do if the expression evaluates to `null`? Ignore it? Wouldn't you want to know why any of those values was `null`, and log the problem? Or would you just show the user a message like "something went wrong somewhere, but we don't know what because we threw away the error", and then hope it doesn't happen again? – adw Nov 01 '10 at 17:07
  • 11
    @adw Whatever you want, it's just better than building up a huge Javaesque chain of `if( addressbook != null && addressbook.people != null && addressbook.people.tim_yates != null...` etc... You still need to make the same decision, but it's a shorter, prettier journey to get there – tim_yates Nov 01 '10 at 17:09
  • @tim_yates: No! That's just as wrong. With a proper design, you would have something like `addressbook = GetAddressBookFromDatabase(db)` and the method throws an exception if it cannot connect / cannot find the addressbook / etc. Then you catch the exception and handle it! And if `addressbook == null` when you try to use it, it's a bug in your code and it **should** cause an error, which you catch somewhere way up the callchain (since it should never happen, you don't have to catch it immediately). – adw Nov 01 '10 at 17:29
  • 3
    @adw `addressbook` was just an example (maybe a badly thought out one), I was just trying to show where the null-safe operator is useful, not start a theological war – tim_yates Nov 01 '10 at 17:35
  • For the sake of comparison, ruby has a similar feature, the [`Object.try`](http://api.rubyonrails.org/classes/Object.html#method-i-try) method. It solves the same problem, but the ruby approach is more methody and less operatory. – ataylor Nov 02 '10 at 16:33
  • 1
    i think the OP wants the feature more in DTO objects. so trying to output the age of the person doesn't have to be a speghetti of code – andho Jun 06 '11 at 08:53
  • 1
    This may be added in a future version of Python https://www.python.org/dev/peps/pep-0505/ – Kellen Donohue Oct 23 '20 at 23:24

7 Answers7

18

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.


  1. No, there isn't.

  2. 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.

  3. 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.

  4. 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?

Paaksing
  • 432
  • 1
  • 4
  • 17
  • 3
    Regarding #3 - There are many times you want to check if something is null. For example, any equality comparison on strings ends up being much cleaner to write `my_string?.strip().lower()` and much easier to read. – Joseph Apr 30 '20 at 14:58
  • Another Regarding #3 - I'm running into this as well in a situation where I am creating reusable code for process safe and single-threaded cases. If the user (i.e., application) is a single process app, it may not want to access a Pipe as it doesn't care to communicate to another process. Would be nice to write `self.pipe?.send(message)` – LeanMan Jan 06 '21 at 00:35
  • @LeanMan #3 already addresses this case by mentioning null objects. In the situation you mention, `self.pipe` would ideally not be `None` but instead should be an instance of e.g. `DoNothingPipe`, which implements a no-op `send` method. – Andrzej Doyle May 04 '21 at 10:55
  • I guess but now you have to write extra code when the point was to be brief – LeanMan May 06 '21 at 20:34
13

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:

nealmcb
  • 12,479
  • 7
  • 66
  • 91
  • Additional discussion about PEP 505: https://discuss.python.org/t/pep-505-status/4612 --- similar functionality for the existing Python: https://github.com/Syeberman/weakget --- in the context of other languages: https://en.wikipedia.org/wiki/Safe_navigation_operator – pabouk - Ukraine stay strong Jun 01 '21 at 08:21
6

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 :-)

hendrixski
  • 1,124
  • 1
  • 12
  • 20
  • Very likely, it isn't implemented like that, but like: testv = possiblyNull.value; if not tesv: return None; return testv.value – zakmck Feb 25 '21 at 18:17
2

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 [].

kindall
  • 178,883
  • 35
  • 278
  • 309
2

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
André Laszlo
  • 15,169
  • 3
  • 63
  • 81
0

Answering your question: yeah, you need to write if-esle clause, but use the pythonic way:

variable.method() if variable else None
storenth
  • 967
  • 11
  • 18
-1

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.

Dirk
  • 30,623
  • 8
  • 82
  • 102
  • 2
    I agree, but `None` is essentially the same in this case. Instead of a `NullPointerException` I would get an `AttributeError`, but I could not call a method on `None` which would be present in usual object such as a list. – deamon Oct 31 '10 at 21:30
  • 2
    The point is, that `None` is not "unusual" at all. It is an object with a proper class, has methods, etc. There is nothing in the language which would make it special in any way (besides, that it is being used to represent the "nothing interesting here" value). So, what would the hypothetical `?.` operator test for? For `None` specifically? What about other libraries which use other markers (e.g., `NOT_FOUND` in PEAK)? – Dirk Oct 31 '10 at 21:37
  • 2
    `None` is great for marking optional function arguments and various other things, but using it (or something like `NOT_FOUND`) as a "not found" result or other special return value should be avoided. Using exceptions for these kinds of exceptional conditions is better because it tends to simplify code using those functions (instead of checking every return value, you can have an except clause, or just let the exception bubble up). – adw Oct 31 '10 at 21:45
  • @adw: One could argue, that exceptions should be used just for exceptional situations, and a value not being present in a dict, say, might or might not be exceptional depending on the circumstances, but let's not get into that. I was merely pointing out, that there actually are such uses for objects different from `None` and there is nothing in the language except convention, which would favour `None` as target for a special `?.` operator. – Dirk Nov 01 '10 at 12:29
  • 3
    this is mainly an opinion piece. DB nulls map to none, uninitialized objects map to none, throws exception same way and usage as null, acts like null, quacks like null, is null. – nurettin Apr 03 '19 at 06:42
  • 3
    What the op means is if there is an operator like Groovy's `?.`. This question is valid regardless of the null nature. – Xwtek May 27 '20 at 23:54
  • The question is: what is `?.` supposed to do? In a language with dedicated `null` value, `x?.y` is roughly equivalent to `x.y if x is not the_magic_null_value else the_magic_null_value` (in pythonesque syntax). But if the language has no `magic_null_value` (and whether `None` qualifies is up to debate as can be seen in the PEP discussing this feature) -- what should the `?.` actually do? – Dirk Dec 27 '22 at 10:30