|
|
Subscribe / Log in / New account

Adding None-aware operators to Python?

By Jake Edge
August 1, 2018

A PEP that has been around for a while, without being either accepted or rejected, was reintroduced recently on the python-ideas mailing list. PEP 505 ("None-aware operators") would provide some syntactic sugar, in the form of new operators, to handle cases where variables might be the special None value. It is a feature that other languages support, but has generally raised concerns about being "un-Pythonic" over the years. At this point, though, the Python project still needs to figure out how it will be governed—and how PEPs can be accepted or rejected.

None-awareness

The basic idea is fairly straightforward. Patterns like the following:

    if x is None:
        x = 42
could be replaced with a more compact, and possibly more readable, version:
    x = x ?? 42
or the even more compact:
    x ??= 42
So, two new operators would be defined. The first is "??", which returns the left-hand side if it is not None and the right-hand side otherwise; importantly, it does not evaluate the right-hand side at all unless the left side is None. As with other "augmented assignment" operators (e.g. +=), "??=" simply applies the ?? operator to the two arguments and assigns the result to the left-hand side.

In that same vein, None-aware indexing and attribute-access operators can change code like the following:

    if x is not None and x['foo'] == 'bar':
        ...

    if y is not None and y.foo == 'bar':
       ...
to:
    if x?['foo'] == 'bar':
        ...
	
    if y?.foo == 'bar':
        ...
The operators can, of course, be combined, as the following example from the PEP shows. The first line is an expression from the email/generator.py file in the standard library, while the second is a rewrite using the new operators:
    mangle_from_ = True if policy is None else policy.mangle_from_

    mangle_from_ = policy?.mangle_from_ ?? True

Readers who think some or all of that looks more like Perl—or, more pejoratively, like line noise—than Python are not alone. That is probably one of the most common complaints heard after Steve Dower reintroduced the PEP in mid-July (as well as in previous discussions of the PEP). In that message, he noted that it might not be the best time to bring up the PEP, given the fact that there was no agreed-upon way for the PEP to be accepted (or, for that matter, rejected) since the recent resignation of Guido van Rossum; "but since we're likely to argue for a while anyway it probably can't hurt (and maybe this will become the test PEP for whoever takes the reins?)."

"Argue for a while" is what followed. Many were simply opposed to any of the operators, largely because of their supposed un-Pythonic nature. But some were more open to just adding ?? (and ??=); the None-aware indexing and attribute-access operators (?[] and ?., also known as "maybe-subscript" and "maybe-dot") can be strung together in ways that seem potentially confusing so folks seemed more wary of them. There are also differing opinions on the readability of the resulting "one-liners"—even advocates of the new operators do not seem inclined toward using them willy-nilly.

Spelling

Many of the arguments against the operators boil down to how they are "spelled"; this is the root of the "un-Pythonic/Perl-like/line-noise" argument. But that's only part of the discussion—or should be. If there is utility to replacing the canonical way to default a variable, how to spell the operator (or keyword) should be a secondary consideration; as Steven D'Aprano put it:

*Its just spelling*. If it is a useful and well-defined feature, we'll get used to the spelling soon enough.

That's not to say that spelling is not important *at all*, or that we should never prefer words to symbols. But if the only objection we have is "this is useful but I don't like the spelling so -1" then that's usually a pretty weak argument against the feature.

Giampaolo Rodolà is concerned that most of the new operators are not "explicit", effectively arguing that they run aground on the "explicit is better than implicit" guideline in The Zen of Python. As he put it:

I personally don't find "a ?? b" too bad (let's say I'm -0 about it) but idioms such as "a?.b", "a ??= b" and "a?[3] ?? 4" look too Perl-ish to me, non pythonic and overall not explicit, no matter what the chosen symbol is gonna be. It looks like they want to do too much for the sole reason of allowing people to write more compact code and save a few lines. Compact code is not necessarily a good thing, especially when it comes at the expense of readability and explicitness, as I think is this case.

D'Aprano argued that any new operators are going to have to look somewhat strange since all of the non-strange operators are already in use. Rodolà said that was part of his point: "Not to state the obvious but it's not that we *have to* use the remaining unused symbols just because they're there." David Mertz went even further, arguing that the PEP 572 approval has pushed things too far:

I think the bar has been much too low for introducing new features over the last 5 years or so. Internal changes like the new dictionary implementation are fine, but user-facing changes should be exceedingly rare in the base language. This proposal doesn't come remotely close to such a good standard.

I was consistently +0 on the 572 idea, as long as its worst excesses were trimmed, as in the final PEP. But after reading this discussion, I almost reconsider that opinion since its social effect seems to be a move towards accepting wild and unnecessary changes that "might be useful" for a few unusual programming patterns.

The argument over the explicitness of the new operators spawned a huge sub-thread, where it was pretty clear that no minds were being changed. Rodolà argued that the implicit check for None used by the operators makes them non-explicit. On the other hand, D'Aprano argued that if the operators are defined to do a particular thing, then using them that way is explicit. The whole argument caused him to proclaim:

Comments like the above is why I think that "explicit" and "implicit" are used to mean "I like it" and "I don't like it" rather than being objective arguments, or indeed having anything to do with explicitness or implicitness.

Nicholas Chammas observed that perhaps it was not a difference of explicit versus implicit, but instead related to something that C++ inventor Bjarne Stroustrup once said:

This reminds me of something I read about once called Stroustrup's Rule:

> For new features, people insist on LOUD explicit syntax.
> For established features, people want terse notation.

I think the "explicit vs. implicit" part of this discussion is probably better expressed as a discussion about "loud vs. terse" syntax. None of the operators in PEP 505 have implicit behavior, to the best of my understanding. It's just that the operators are new and have terse spellings.

Limbo

Along the way, Dower tried to refocus the discussion by presenting some of the arguments being made that he found lacking, along with a rebuttal of each. That apparently did not have the desired effect, as he bowed out of the discussion shortly thereafter:

I had assumed that because my emails are not the PEP that people would realise that they are not the PEP. I'm going to duck out of the discussions here now, since they are not as productive as I'd hoped, and once we have a BDFL-replacement I'll reawaken it and see what is required at that point.

For some, that may be just as well. Raymond Hettinger said that he was worried that it was not the right time for a discussion of PEP 505 as it might introduce "divisiveness when we most need for be focusing on coming together". Furthermore, he was not a fan of the feature for a number of reasons:

This PEP also shares some traits with PEP 572 in that it solves a somewhat minor problem with new syntax and grammar changes that affect the look and feel of the language in a way that at least some of us (me for example) find to be repulsive.

This PEP is one step further away from Python reading like executable pseudo-code. That trait is currently a major draw to the language and I don't think it should get tossed away just to mitigate a minor irritant.

He also noted that other implementations of Python are having a hard time keeping up with the "ferocious rate of change" in recent Python releases, so he thinks a moratorium on language changes makes sense. He listed off a long string of features that have been added and wondered how many folks—including CPython core developers—were on top of all of them. "We've been putting major changes in faster than anyone can keep up with them. We really need to take a breath."

Informally, a moratorium is what the participants in a thread on the python-committers mailing list (where only core developers can post) have more or less recognized. There is a de facto moratorium because of a lack of a way to decide on a PEP, but, even once that logjam has cleared (currently planned to be completed early in 2019), it seems likely that any major changes will push out to Python 3.9 (currently targeted for 2021)—at the very least.

The discussion of PEP 505 may serve another purpose, as well. Discussions of PEPs in python-ideas are supposed to be more freewheeling and potentially fractious, but the scars of PEP 572 linger in many ways. This discussion may fuel the efforts to find other ways to discuss PEPs once they reach the point where they might be decided upon (and would typically then move to the python-dev mailing list). Presumably, discussions on python-ideas would stay the same, but what happens after that might be in for some changes—much like the Python project itself at this point.


Index entries for this article
PythonNone
PythonPython Enhancement Proposals (PEP)/PEP 505


to post comments

Adding None-aware operators to Python?

Posted Aug 1, 2018 16:23 UTC (Wed) by acarno (subscriber, #123476) [Link]

I mentioned this late on a previous post, but I'll say it again here: I'd suggest implementing a discussion board for PEPs that takes into account the best features of forums across the internet:

- StackOverflow's Q/A format
- Hacker News' hidden points
- Reddit's "best" sorting algorithm [1]

It could tamp down on the sheer number of emails (you could follow specific posts/reply threads) and perhaps limit the amount of bike shedding (presumably comments with more substantial replies get a higher ranking).

No idea if it would work, but I figure it's worth putting the idea out there. I'd love to hear feedback/critiques.

[1] https://redditblog.com/2009/10/15/reddits-new-comment-sor...

Two words: reader macro

Posted Aug 1, 2018 17:16 UTC (Wed) by quotemstr (subscriber, #45331) [Link] (3 responses)

Lisp famously has regular macros, which are functions that can manipulate the AST before evaluation. It also has, less famously, "reader macros", which basically extend the lexical structure of the language and allow for arbitrary syntax in DSLs. Something like this Python proposal could easily be implemented as a reader macro. I've wanted macro support for Python for ages now, and existing hacks to implement similar functionality aren't really usable.

Two words: reader macro

Posted Aug 1, 2018 18:09 UTC (Wed) by rgmoore (✭ supporter ✭, #75) [Link] (2 responses)

I think any proposal for Python macros is likely to be dismissed out of hand. Look at how much resistance a handful of relatively minor pieces of syntactic sugar have faced. One of the things Python people really love about their language is its simple, consistent syntax. Python has only one standard dialect, so any experienced programmer can read somebody eles's program and understand what it's doing. Allowing anyone to make arbitrary syntax changes blows that up.

Two words: reader macro

Posted Aug 2, 2018 6:47 UTC (Thu) by brooksmoses (guest, #88422) [Link]

Well, dismissed out of hand as part of the Python language, sure.

But you could do it as something like Ratfor, where it's something implemented as a distinct preprocessor rather than part of the language itself. If it caught on about as much as Ratfor did -- which is to say, being handy for exploring language ideas but never really getting widespread use of any sort -- that might be a useful thing to have around.

Two words: reader macro

Posted Aug 6, 2018 0:22 UTC (Mon) by sionescu (subscriber, #59410) [Link]

Due to decorators, locals(), self.__getattr__(), etc... it's not true that you can understand any Python code without having to understand exactly how things are implemented.

Adding None-aware operators to Python?

Posted Aug 1, 2018 17:51 UTC (Wed) by marduk (subscriber, #3831) [Link] (3 responses)

mangle_from_ = True if policy is None else policy.mangle_from_

mangle_from_ = policy?.mangle_from_ ?? True
As a long-time perl-to-python convert and native English speaker, it's going to be really difficult to convince me that the latter is easier to read than the former. Additionally I don't understand why the latter would be preferred other than it saves 19 characters. It mostly seems cute for the sake of being cute, but in my opinion it's not.

Adding None-aware operators to Python?

Posted Aug 1, 2018 21:17 UTC (Wed) by quietbritishjim (subscriber, #114117) [Link]

I agree with your point, but the second line is actually equivalent to this, which is admittedly even more verbose:
    mangle_from_ = (
        True if policy is None or policy.mangle_from_ is None 
        else policy.mangle_from_
    )
I think it's no big deal to go ahead and use an if statement here, and I have assumed it suffices to test for truthiness of the structure (I'm guessing that when chaining ?? like this, that's usually going to be fine in all but the last comparison):
    if policy and policy.mangle_from_ is not None:
        mangle_from_ = policy.mangle_from_
    else:
        mangle_from_ = True

Adding None-aware operators to Python?

Posted Aug 2, 2018 8:27 UTC (Thu) by flup (guest, #115570) [Link]

I agree. It seems to me that, as newcomers to the language become seasoned Python programmers, their familiarity with the syntax leads them to crave shorthand for what they start to perceive as long-winded code. In my view this should be resisted. Python's readability is one of its great strengths, and proposals like this replace self-evident meaning with C-like obfuscation.

Adding None-aware operators to Python?

Posted Aug 2, 2018 20:35 UTC (Thu) by flussence (guest, #85566) [Link]

Amusingly, that bottom line is only a few characters off being valid perl6:
mangle_from_ := policy.?mangle_from_ // True
…though perhaps not perl code anyone would want to write or read. Something more idiomatic would go like:
with policy {
  mangle_from_ := policy.mangle_from_;
  …
}
else {
  mangle_from_ := True;
  # assign other defaults
}

C#

Posted Aug 1, 2018 19:33 UTC (Wed) by epa (subscriber, #39769) [Link]

Worth noting that both these operators exist in C# and may have originated there. They are handy shortcuts, although this kind of thing is slightly more user-friendly in a statically typed language where you can get immediate feedback about what things can be null (or None) and what can't.

Adding None-aware operators to Python?

Posted Aug 2, 2018 2:18 UTC (Thu) by sml (guest, #75391) [Link] (3 responses)

I find it amazing that this proposition is being seriously considered.

The raison d'être of python is explicit verbosity AKA executable pseudocode.

If this goes in after PEP572 then the value proposition of Python is significantly lowered because it become more Perl/Rubyish. In that case, why would I use Python for my line-noise scripts over Perl or Ruby?

Adding None-aware operators to Python?

Posted Aug 2, 2018 5:30 UTC (Thu) by quotemstr (subscriber, #45331) [Link] (2 responses)

Were you also against the addition of the += operator?

Adding None-aware operators to Python?

Posted Aug 2, 2018 20:06 UTC (Thu) by tartley (subscriber, #96301) [Link] (1 responses)

I personally find '+=' much easier to reason about - there is no hesitation our confusion while I momentarily expand (or simulate the execution of) the syntax in my head.

Perhaps people who are in favor don't experience this with '?[', etc. Perhaps it's a matter of familiarity of similar features in other languages. Or perhaps it's a genuine distinction between widely intuitive and simplifying syntax versus a needless obfuscation. I'm not trying to be judgemental with that language. I'm positing a genuine question.

I'd love to hear any positions that could genuinely help differentiate, as opposed to just pouring more opinions on the flames.

Adding None-aware operators to Python?

Posted Aug 3, 2018 16:11 UTC (Fri) by felixfix (subscriber, #242) [Link]

Personal preferences differ all over the map. The languages I am happiest with allow such diverse preferences. The programmers I am happiest working with are also tolerant of differing styles.

I can see advantages of rigid languages for some esoteric cases. Maybe medical devices or nuclear weapon control should be such. But there are always trade-offs -- for every seen characteristic, there are more unseen trade-offs, and Bastiat isn't the only one who wishes more people would see them.

As is almost always the case, flexibility and adaptability win the day. I have no stake in this matter, but that's partly because I dislike the rigid thinking that created this discussion out of thin air.

Adding None-aware operators to Python?

Posted Aug 2, 2018 10:22 UTC (Thu) by fagan (guest, #60302) [Link] (3 responses)

I use if xyz is None regularly and I think this would be a welcome change. While I understand the non-pythonic nature of it I still think it's a quality of life improvement. As for which one is better x = x ?? 32 sounds a bit more readable.

Adding None-aware operators to Python?

Posted Aug 2, 2018 14:36 UTC (Thu) by acarno (subscriber, #123476) [Link] (2 responses)

> While I understand the non-pythonic nature of it I still think it's a quality of life improvement.

This strikes me as doublethink (if you'll excuse the Orwellian reference). Sure, the syntax is a quality of life improvement for experienced developers, but if it's non-Pythonic, isn't that reason enough for it *not* to belong in the *Python* language? It seems to cut to the heart of that question: for what purpose was a language written?

A better solution, in my opinion, would be to switch to a language that offers such compact syntax (Perl? I'm not sure, never used it). That requires leaving the Python ecosystem, however, which is of course a non-starter if your entire software stack uses Python. I guess there's not much of a way around that problem unfortunately.

Adding None-aware operators to Python?

Posted Aug 2, 2018 17:03 UTC (Thu) by epa (subscriber, #39769) [Link] (1 responses)

Isn't it a bit circular to define what is Pythonic in relation to the current version of the Python language? I thought that "Pythonic" was used to describe a way to write programs (for example, it is often more common to access a dictionary element and catch an exception, rather than check for its existence first) rather than as a way to decide what changes should be made to the language.

Adding None-aware operators to Python?

Posted Aug 2, 2018 22:47 UTC (Thu) by rgmoore (✭ supporter ✭, #75) [Link]

Isn't it a bit circular to define what is Pythonic in relation to the current version of the Python language?

I don't think that's what's happening. I'm not a Python programmer myself, but I get the impression that a huge part of what makes Python Python- and what makes it popular- is that it has an aesthetic sense of what the language is supposed to be like. Part of that is the idea that it's more important to be clear than to be concise, and something like ??= (or worse foo?.[bar]) offends that sense of what Python is supposed to be like. I use Perl, so I'm used to constructs like //= and they don't bother me, but I can certainly understand somebody not wanting that in their language because it goes against what the language is supposed to be like.

Interesting comparison to COBOL

Posted Aug 2, 2018 14:46 UTC (Thu) by felixfix (subscriber, #242) [Link] (6 responses)

As an ancient non-Pythonista programmer who has done his fair share of Perl, the main argument, that verbosity is good, gives me not-so-friendly reminders of why I never learned any more COBOL than I ever had to (being to copy a COBOL program from a fifth generation photocopy to see if a new COBOL compiler could handle it; I remember being astounded that every "sentence" had to end with a period. I hope it's gotten less anal by now.).

Verbosity is fine for beginners or suits. Once you gain any familiarity with a language, you get tired of "ADD 1 TO EMPLOYEE-PAYROLL-SUM RESULTING IN EMPLOYEE-PAYROLL-SUM" and salivate at those lucky FORTRAN programmers who can fit the entire statement on a single line.

I vaguely remember someone coming up with a COBOL translator which would let you use abbreviations and shortcuts in your source, then convert it to regulation verbosity for compilation. Maybe Pythonistas could do the same, unofficially of course, if verbosity is the official mantra.

You get used to verbosity and shortcuts. It's just familiarity. I suppose Perl programmers think of APL as line noise and APL programmers feel pity for those poor Perl programmers.

It's all programming. I understand purists wanting to preserve what they are used to, but I've programmed in too many different environments with too many different personal styles to have much sympathy for the practicality of static systems. Be flexible or suffocate is my motto. If you can't adjust to variation, if deviations trigger you, if diversity threatens you, then your designs will be equally stagnant and unforgiving.

Interesting comparison to COBOL

Posted Aug 2, 2018 16:42 UTC (Thu) by naptastic (guest, #60139) [Link] (1 responses)

May I quote you on this, and to whom should I make the attribution?

Interesting comparison to COBOL

Posted Aug 2, 2018 17:13 UTC (Thu) by felixfix (subscriber, #242) [Link]

Well I never ....! :-) and so on.

Can't remember ever being asked that before. I have no idea how to respond. If it's any help, I am no fan of copyrights, so quote at will, and as for attribution, well, there's a handle already in place.

Heavens to Betsy!

Interesting comparison to COBOL

Posted Aug 3, 2018 11:56 UTC (Fri) by NAR (subscriber, #1313) [Link] (3 responses)

As the saying goes, code is made for reading, not writing. If writing long operators, variables, function names, etc.is cumbersome, that's where the IDE should help with autocompletion. If there's too much extra stuff, syntax highlight can help. So I think there are tools to help the advanced programmer to have his shortcuts while keeping the code readable for the next generation...

Interesting comparison to COBOL

Posted Aug 3, 2018 15:01 UTC (Fri) by nybble41 (subscriber, #55106) [Link] (2 responses)

> If writing long operators, variables, function names, etc.is cumbersome ...

This isn't a matter of easer of reading vs. ease of writing. *Reading* long operators, variables, function names, etc. is equally cumbersome. People speak derisively of languages whose syntax resembles "line noise", but repeating the same long name or awkward syntax a dozen times in the same function when something shorter would have been just as easy for the target audience to understand is merely another kind of noise.

Interesting comparison to COBOL

Posted Aug 3, 2018 16:21 UTC (Fri) by felixfix (subscriber, #242) [Link] (1 responses)

It's also a matter of experience. Verbosity can help when reading a program for the first time, or in a language not often used. But maintaining such a program makes it hard to follow. Long variable names can fool the eye into misreading them. People's brains are very good at skimming long words and using context to guess what they probably are; most readers have had the experience of getting confused a few words later and having to back track to find where one's understanding went astray.

It is the same with programs. I know I have been misled more than a few times by long variable and function names that my mind is reluctant to study carefully every time I see it. When a program is full of 20-30 character variables and methods, it bogs me down and makes it harder to understand the code. On the other hand, if I am skimming code for a general understanding, it's not as important. If someone tells me to interface to some method, sometimes the functionality is not clear and I need to read the code to know what it actually does, but I have never seen it before and don't expect to ever see it again. Then longer names may be more useful.

Interesting comparison to COBOL

Posted Aug 4, 2018 12:23 UTC (Sat) by madscientist (subscriber, #16861) [Link]

When I was a young programmer I read Rob Pike's Notes on Programming in C and it was very influential on me... which is probably to say it aligned with and clarified my natural inclinations.

Many of the suggestions there are specific to C, and even to C of the late 1980's/early 1990's, but the typography advice is still something I tend to follow today.

Adding None-aware operators to Python?

Posted Aug 2, 2018 18:21 UTC (Thu) by jezuch (subscriber, #52988) [Link] (2 responses)

I kind of find it amusing, all those wishing for null-safe or None-safe operators. From my point of view it looks like people wish for monads without realising it. And without understanding the theory. And it *is* very implicit, this monad-ness of it all. I'm not a Python programmer but it's not just Python, sooner or later it appears everywhere. Or at least where there are not already monads :)

Adding None-aware operators to Python?

Posted Aug 3, 2018 8:14 UTC (Fri) by marcH (subscriber, #57642) [Link] (1 responses)

Sounds like the perfect time for a simple monad example.

Adding None-aware operators to Python?

Posted Aug 9, 2018 6:49 UTC (Thu) by HelloWorld (guest, #56129) [Link]

Python already has syntax for two monads: list comprehensions and await/async, so if you need an example, look at any program using those.

Adding None-aware operators to Python?

Posted Aug 2, 2018 19:57 UTC (Thu) by naptastic (guest, #60139) [Link]

Earlier in my career, I had to maintain a suite of software written in Perl, which had to be compatible with 5.8.8 and only use core modules. The rest of the company was writing code for Perl 5.14 and newer. If I had a dollar for every time I wanted //= ("defined or", which was added in Perl 5.10) but couldn't use it, my house would be paid off by now.

Add it. Add it now and don't look back.

(Just don't add sigils.)

Adding None-aware operators to Python?

Posted Aug 3, 2018 8:19 UTC (Fri) by marcH (subscriber, #57642) [Link] (2 responses)

> But that's only part of the discussion—or should be. If there is utility to replacing the canonical way to default a variable, how to spell the operator (or keyword) should be a secondary consideration;

So once again, divide and conquer (and maybe don't upset the next BDFL):

- 1st PEP : is the current syntax too long and worth new, unspecified operators?

- Only if the 1st PEP is approved, 2nd PEP: debate the new syntax.

Adding None-aware operators to Python?

Posted Aug 3, 2018 8:53 UTC (Fri) by excors (subscriber, #95769) [Link] (1 responses)

I'm not sure how you can decide if new syntax would be "worth" it, based purely on evaluating the current syntax. All syntaxes have benefits and costs, and (unless the current syntax is really dreadful) you can't improve both the benefits and costs - you have to trade off one against the other, usually by increasing conciseness while decreasing readability. If you just look at a piece of current syntax then of course it has some costs (e.g. verbosity) and everybody would like to reduce costs, but you need to compare it to a specific instance of new syntax to decide if the new tradeoff is an overall improvement or not.

Otherwise it seems a little bit like the politician's syllogism - "PEP 1: We must change the syntax. PEP 2: This is a change to the syntax. Therefore we must implement PEP 2".

Adding None-aware operators to Python?

Posted Aug 3, 2018 14:02 UTC (Fri) by marcH (subscriber, #57642) [Link]

> I'm not sure how you can decided [...] based purely on evaluating the current syntax.

Agreed: I'm not sure how you can erase memories and convince yourself you never saw something :-)

1. Do you find *any* of the newer syntaxes offered better? YES/NO question, binary answer. Look at all propositions but not allowed to bikeshed yet.
2. If 1. is yes, then discuss and chose one.

Besides focusing the discussions it also lets the (minority of) people who vote "no" choose what they find to be the lesser of all evils if they lost.

If no majority in step 2. then too bad: no new syntax. Now you could have people "gaming the system" and defending unpopular propositions not because they like it but just to make the whole process fail, however I hope most people in this case wouldn't go down that low.

You can further break down 2. into two steps by grouping propositions into "classes" of similar variants, example:

2.1 which pseudo-YACC code do you prefer?
2.2 which pseudo-LEX code do you prefer?

Discussions about syntax/most basic language features are always passionate - hence messy and very unproductive. So anything that can bring some order to them would help.

Adding None-aware operators to Python?

Posted Aug 3, 2018 9:17 UTC (Fri) by mb (subscriber, #50428) [Link] (4 responses)

You can just write

> if x is None: x = 42

instead of this unreadable !@^%^&#%$

> x = x ?? 42

I don't oppose against adding new operators. Like := for example, which does actually make code more readable and even sometimes perform better by reducing redundancy such as in comprehensions.
One of the best things of the Python language is that lots of expressions and even statements can be read as an English sentence.
For that reason the 'and' operator is better than having &&, even if && is less characters to type.
Same goes for ??. We already have syntax to express the exact same thing. Just use that and abandon ??.

Adding None-aware operators to Python?

Posted Aug 4, 2018 7:27 UTC (Sat) by epa (subscriber, #39769) [Link] (3 responses)

It’s more about

x = g()
f(42 if x is None else x)

That can be simplified to

f(g() ?? 42)

avoiding the intermediate variable altogether.

Adding None-aware operators to Python?

Posted Nov 14, 2021 11:06 UTC (Sun) by diegor (subscriber, #1967) [Link] (2 responses)

What about using a function?
def nvl(v, default):
  if v is None:
    return default
  else:
    return v
f(nvl(g(),42)) Eventually nvl() can be made a standard library function.

Adding None-aware operators to Python?

Posted Nov 14, 2021 13:44 UTC (Sun) by mathstuf (subscriber, #69389) [Link] (1 responses)

That doesn't work for:

f(nvl(g(), expensive()))

because the `expensive()` will be called even if `g()` is not `None`.

Adding None-aware operators to Python?

Posted Nov 14, 2021 21:05 UTC (Sun) by nybble41 (subscriber, #55106) [Link]

Like many things, this can be fixed with some indirection:

def nvl(v, default):
  if v is None:
    return default()
  else:
    return v

f(nvl(g(), lambda: expensive()))

Adding None-aware operators to Python?

Posted Aug 7, 2018 21:50 UTC (Tue) by mirabilos (subscriber, #84359) [Link] (2 responses)

This would be really useful.

It’s one of the things C# has, and which I kind of envy, especially in crapuages like Java™.

We need object.anotherobject.yetanotherobject.method() way too often, and just propagating nil as result if one of the chain is nil alone would be a GREAT help, let alone some of the other possibilities described.

Adding None-aware operators to Python?

Posted Aug 7, 2018 22:21 UTC (Tue) by Cyberax (✭ supporter ✭, #52523) [Link] (1 responses)

> We need object.anotherobject.yetanotherobject.method() way too often
That's a sign of a bad design, btw. See: https://en.wikipedia.org/wiki/Law_of_Demeter

Adding None-aware operators to Python?

Posted Aug 8, 2018 0:06 UTC (Wed) by mirabilos (subscriber, #84359) [Link]

Only if you’re working with independent modules,
not if you’re working with local/known-to-the-application
nested data structures or somesuch.

(It’s also a meta-answer and as such does not contribute to the discussion on the topic itself.)

Adding None-aware operators to Python?

Posted Aug 10, 2018 23:33 UTC (Fri) by Pc5Y9sbv (guest, #41328) [Link]

Having to swap between Python and SQL a lot lately, I sometimes try to imagine having Python None act more like SQL NULL. It can be very convenient to rely on expressions evaluating to None and using COALESCE(expr, ...) to supply fallback expressions to try in order when you don't want a None value.

However, the mechanism in SQL is more than just guarding for NULL values. Many valid operator and function-call scenarios will return NULL with NULL inputs:

(NULL::integer) + 5 --> NULL
(NULL::foo_type).id --> NULL # if foo_type has a field id
some_array[NULL::integer] --> NULL
(NULL::integer[])[5] --> NULL

as opposed to raising errors in Python:

None + 5 raises TypeError
None.id raises AttributeError
some_list[None] raises TypeError
None[5] raises TypeError
None(5) raises TypeError # no equivalent in SQL, since functions are not expressions

but, given the different type systems, SQL NULL does not blindly suppress usage errors:

NULL::text + 5 raises error # text+integer operator does not exist
(NULL::foo_type).bar raises error # if foo_type does not have field bar
some_array[NULL:text] raises error # text is not a valid subscript
(NULL::integer)[5] raises error # integers do not support array subscripts

It would be quite a different language to introduce typed expressions and typed NULLs like this. But, if Python had gone with something like NullValueException for common error cases above, we could imagine using exception handling to emulate much of the useful NULL handling in SQL. We'd still need new special syntax for coalesce() unless we want to wrap expressions in thunks to delay their execution:

def coalesce(*args):
  for arg in args:
     try:
       result = arg()
       if result is not None:
         return result
     except NullValueException:
       pass

coalesce(lambda: x[y], lambda: z+2, lambda: 42)

I agree with others above that an operator that only guards literal None values seems silly, when you can already write a conditional expression that directly communicates your intent:

x = x ?? 42
# does each variant below communicate expectations about common case?
x = x if x is not None else x
x = 42 if x is None else x

The main power of NULL-safe expressions is when the NULL can be encountered in deeply nested functional expressions and captured, much like exception handling lets us selectively abort or intercept imperative call chains.


Copyright © 2018, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds