[Python-ideas] Null coalescing operators
Trent Nelson
trent at snakebite.org
Fri Sep 18 20:21:39 CEST 2015
On Fri, Sep 18, 2015 at 10:42:59AM -0700, Mark Haase wrote:
> StackOverflow has many questions
> <http://stackoverflow.com/search?q=%5Bpython%5D+null+coalesce> on the
> topic of null coalescing operators in Python, but I can't find any
> discussions of them on this list or in any of the PEPs. Has the
> addition of null coalescing operators into Python ever been discussed
> publicly?
>
> Python has an "or" operator that can be used to coalesce false-y
> values, but it does not have an operator to coalesce "None"
> exclusively.
Hmmm, I use this NullObject class when I want to do stuff similar to what
you've described:
class NullObject(object):
"""
This is a helper class that does its best to pretend to be forgivingly
null-like.
>>> n = NullObject()
>>> n
None
>>> n.foo
None
>>> n.foo.bar.moo
None
>>> n.foo().bar.moo(True).cat().hello(False, abc=123)
None
>>> n.hornet(afterburner=True).shotdown(by=n().tomcat)
None
>>> n or 1
1
>>> str(n)
''
>>> int(n)
0
>>> len(n)
0
"""
def __getattr__(self, name):
return self
def __getitem__(self, item):
return self
def __call__(self, *args, **kwds):
return self
def __nonzero__(self):
return False
def __repr__(self):
return repr(None)
def __str__(self):
return ''
def __int__(self):
return 0
def __len__(self):
return 0
Source: https://github.com/tpn/tpn/blob/master/lib/tpn/util.py#L1031
Sample use: https://github.com/enversion/enversion/blob/master/lib/evn/change.py#L1300
class ChangeSet(AbstractChangeSet):
@property
def top(self):
"""
Iff one child change is present, return it.
Otherwise, return an instance of a NullObject.
"""
if self.child_count != 1:
return NullObject()
else:
top = None
for child in self:
top = child
break
return top
@property
def is_tag_create(self):
return self.top.is_tag_create
@property
def is_tag_remove(self):
return self.top.is_tag_remove
@property
def is_branch_create(self):
return self.top.is_branch_create
@property
def is_branch_remove(self):
return self.top.is_branch_remove
Having self.top potentially return a NullObject simplifies the code for
the four following properties.
> I can implement this behavior myself in pure Python, but it would be
> (a) nice to have it the in the standard library, and (b) even nicer to
> have an operator in the language, since terseness is the goal.
>
> As a motivating example: when writing web services, I often want to
> change the representation of a non-None value but also need to handle
> None gracefully. I write code like this frequently:
>
> response = json.dumps({ 'created': created.isoformat() if created
> is not None else None, 'updated': updated.isoformat() if updated
> is not None else None, ... })
>
> With a null-aware member access operator, I could write this instead:
>
> response = json.dumps({ 'created': created?.isoformat(),
> 'updated': updated?.isoformat(), ... })
If you can alter the part that creates `created` or `updated` to return
a NullObject() instead of None when applicable, you could call
`created.isoformat()` with out the addition clause.
> Thanks, Mark
Trent.
More information about the Python-ideas
mailing list