class NoneCoalesce(object):"Standard operations on object for 'is not None'"def __init__(self, obj):self.obj = objdef __getattr__(self, name):try:return getattr(self.obj, name)except AttributeError:return NoneCoalesce(None)def __getitem__(self, item):try:return self.obj[item]except (TypeError, KeyError):return NoneCoalesce(None)def __call__(self, *args, **kwds):try:return self.obj(*args, **kwds)except TypeError:return NoneCoalesce(None)def __bool__(self):return self.obj is not Nonedef __repr__(self):return "NoneCoalesce[%r]" % self.objdef __str__(self):return "NoneCoalesce[%r]" % self.objdef __len__(self):try:return len(self.obj)except TypeError:return 0
>>> from boltons.dictutils import OrderedMultiDict>>> from NoneCoalesce import NoneCoalesce>>> omd = OrderedMultiDict()>>> omd['a'] = 1>>> omd['b'] = 2>>> omd.add('a', 3)>>> nc = NoneCoalesce(omd)>>> nc or "Spanish Inquisition"Out: NoneCoalesce[OrderedMultiDict([('a', 1), ('b', 2), ('a', 3)])]>>> nc.spam or "Spam"Out: 'Spam'>>> nc['nope'].bar.baz()Out: NoneCoalesce[None]>>> nc['a']Out: 3>>> nc.getlist('a')Out: [1, 3]
I find the '?.' syntax very ugly, much more so in the examples of chained attributes.
A much better way to handle the use case is to wrap objects in a class that gives this "propagating None" behavior with plain attribute access. A nice implementation was presented in this thread.On Sep 10, 2016 3:16 PM, "Random832" <email@example.com> wrote:On Sat, Sep 10, 2016, at 13:26, Guido van Rossum wrote:
> The way I recall it, we arrived at the perfect syntax (using ?) and
> semantics. The issue was purely strong hesitation about whether
> sprinkling ? all over your code is too ugly for Python
I think that if there's "strong hesitation" about something being "too
ugly" it can't really be described as "the perfect syntax". IIRC there
were a couple alternatives being discussed that would have reduced the
number of question marks to one [or one per object which might be None].
Python-ideas mailing list
Code of Conduct: http://python.org/psf/codeofco