2

Given:

variableX = 5
someValueY = 6

Imagine you want to assign to variableX the maximum of variableX and someValueY:

variableX = max(variableX, someValueY)

I more than once figured it would be nice to have something like:

variableX max= someValueY

Comparable to += and the other assignment operators.

Is this a good idea, does it already exist and isn't this Pythonic?

PascalVKooten
  • 20,643
  • 17
  • 103
  • 160
  • I believe this isn't the place for ideas. But it isn't a bad idea – Or Duan Jan 04 '15 at 11:04
  • 2
    Why would it be a good idea? Augmented operations exist to give the left-hand object a chance to make an *in-place change*. `max()` never alters its operands. And that is quite apart from the fact that `max()` *is not an operator*. It is a function, and it takes *more optional arguments*, which you could not pass in if it was an operator. – Martijn Pieters Jan 04 '15 at 11:05
  • @OrDuan: it is a bad idea because there is no point in such an operator. – Martijn Pieters Jan 04 '15 at 11:05
  • 3
    Downvote is not mine, but "why is my favorite compound assignment operator not part of language X" is not very constructive. Such an operator being "Pythonic" looks subjective as well. – Frédéric Hamidi Jan 04 '15 at 11:05
  • 3
    I didn't vote, but the *good idea* and *Pythonic* parts are clearly subjective (and therefore off-topic). I personally don't find this notation intuitive and don't see what it would buy other than a few keystrokes. As to whether it exists, the answer I am afraid is *no*. – NPE Jan 04 '15 at 11:05
  • 1
    To the down voters: notice that part of the question was **does it already exist?** – Jivan Jan 04 '15 at 11:08
  • 1
    That'd be the one bit of the question you didn't answer then @Jivan :-). – Ben Jan 04 '15 at 11:08
  • 1
    @FrédéricHamidi You really made the main point. It could be done with any function of the shape `x = fn(x,y)`. Thanks for pointing that out. – PascalVKooten Jan 04 '15 at 11:10
  • @NPE I agree my notation is not so intuitive, but perhaps there could be a more intuitive one. – PascalVKooten Jan 04 '15 at 11:11
  • ...there is a more intuitive notation, it's `foo = max(foo, bar)`. Note that it reads pretty much exactly how you'd say it - *"foo equals the maximum of foo and bar"*. – jonrsharpe Jan 04 '15 at 11:12
  • @MartijnPieters I know you are very familiar with the language, so I would assume that if the operator existed at this point you would have been using it.... Is that not indicative? – PascalVKooten Jan 04 '15 at 11:12
  • 2
    @jonrsharpe That's wrong. `foo = foo + bar` also reads the same way, yet still we have `foo += bar` – PascalVKooten Jan 04 '15 at 11:15
  • @Ben correct, but fixed now, thanks for pointing this out – Jivan Jan 04 '15 at 11:15
  • 1
    @PascalvKooten: There would never be such an operator, because operators take a *fixed number of operands*. Most operators take 1 or 2 operands, a few take 3 (only one such operator exists in Python). `max()` takes an arbitrary number of values, or it takes *one* operand, a sequence, plus it takes a key to determine the values by and (in Python 3.4 and up) it takes a default value if the sequence was empty. It therefor **must** be a function. – Martijn Pieters Jan 04 '15 at 11:15
  • 1
    @MartijnPieters This is the first answer that actually shows a reason why it cannot/should not be implemented. Then again, I could see `x max= y,z` (`x=max(x,y,z)`) work as well... EDIT: Thanks, the extended part really cleared it up. – PascalVKooten Jan 04 '15 at 11:17
  • IMHO, it'd be non-Pythonic: Explicit is better than implicit. There should be one-- and preferably only one --obvious way to do it. Special cases aren't special enough to break the rules. Etc. – PM 2Ring Jan 04 '15 at 11:42
  • @PascalvKooten if `x max= y, z` should be `x = max(x, y, z)` but `x max= y` should be `x = max(x, y)` then that adds another layer of complexity; `foo func= bar` could be interpreted as `foo = func(foo, *bar)`, but that breaks your original example unless you make the syntax `x max= y,` (note trailing comma for one-tuple). – jonrsharpe Jan 04 '15 at 11:57
  • 1
    The case _for_ is obvious: it's one of the most common tasks that still doesn't have its own operator. For aesthetic reasons, however, `max=` is unlikely to ever be accepted. So it should be an operator made up of special characters only. For starters, it should contain the `<` or `>` characters, as they are related to min/max. Maybe `a <> b` for returning the min and `a >< b` for returning the max of the two values. (Unfortunately `<>` is already mapped to `__ne__`, as is `!=`.) Then `a <>= b` to assign that minimum to `a`, and likewise with `a ><= b`. – Evgeni Sergeev Jul 20 '15 at 11:59
  • 2
    [G++ used to have operators that did this but removed them](https://gcc.gnu.org/onlinedocs/gcc-4.3.1/gcc/Deprecated-Features.html), perhaps because C++ added other ways of computing min and max: "The G++ minimum and maximum operators (`` and `>?`) and their compound forms (`=`) and `>?=`) have been deprecated and are now removed from G++. Code using these operators should be modified to use std::min and std::max instead." – kuzzooroo May 28 '18 at 14:25

2 Answers2

3

Per the language reference, "augmented assignment":

is the combination, in a single statement, of a binary operation and an assignment statement

(emphasis mine). max isn't a binary operation (it takes an arbitrary number of positional arguments plus the key keyword argument), so your proposed operator would not be consistent with the existing suite. You would presumably also want min=, but what about the other built-in functions?


At an implementation level, note that this proposal would mean adding a whole layer of complexity to the parsing of Python code; either there is some exception to parsing if the name happens to be max (or min, or whatever else you want to provide for) or any name would be treated the same way, i.e.:

foo func= bar

would just be syntactic sugar for:

foo = func(foo, bar)

(or func(bar, foo); what if the function isn't commutative?)


In the comments, you mention x max= y, z would become x = max(x, y, z), so either the second argument is a tuple that gets unpacked, e.g.:

foo func= bar

would be translated to:

foo = func(foo, *bar)

(which means that a trailing comma is required for a single value: x max= y,), or we are implementing yet more new syntax.


This is a lot of effort in implementation, testing and maintenance (not to mention another thing for beginners to learn before they can read Python code). Adding new syntax to a language must always have a very strong case and, per the Zen of Python (import this):

There should be one-- and preferably only one --obvious way to do it.

That "one obvious way" is the existing syntax, foo = func(foo, bar). This doesn't apply to the existing suite as, per the relevant PEP

The idea behind augmented assignment in Python is that it isn't just an easier way to write the common practice of storing the result of a binary operation in its left-hand operand, but also a way for the left-hand operand in question to know that it should operate `on itself', rather than creating a modified copy of itself.

For this to apply to max=, we would now have to allow objects to implement e.g. __imax__ (c.f. __iadd__ for +=), which would imply also having a regular __max__ method, and potentially leads on to arbitrary __func__ and __ifunc__ methods, which is yet another can of worms. The more I think about this, the worse an idea it seems...


Within a class, you can implement this with a descriptor to set maximum and minimum values for specific attributes; see e.g. Implementing a decorator to limit setters.

Community
  • 1
  • 1
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
0

What you're asking for is basically the same as:

Why can't we do x++ to increment x ?

The answer is, also, basically the same:

We could, but the benefits are not worth the amount of work and maintainability required.

--

Update: to answer the part of your question which asks does it already exist? - No.

Jivan
  • 21,522
  • 15
  • 80
  • 131
  • 1
    That is an excellent and comprehensive answer *to a completely different question*! – jonrsharpe Jan 04 '15 at 11:10
  • 2
    @jonrsharpe the *completely different question* is in fact *similar*, because it concerns a similar interrogation about a similar concept – Jivan Jan 04 '15 at 11:12
  • 1
    The linked answer provides a good explanation of why `++` **specifically** is not used in Python. It doesn't cover any of the general issues of adding new syntax, including the point your answer makes. It does not actually support your argument (not that it's invalid). – jonrsharpe Jan 04 '15 at 11:14
  • @jonrsharpe I think the part beginning with "I suspect the ++ and -- operators were left out for consistency and simplicity" and then going on with arguments is pertinent here - not saying that it's **exactly** the same, just saying that it's similar and it helps understanding my answer – Jivan Jan 04 '15 at 11:18
  • But none of those arguments are relevant to this case. If there is a parsing ambiguity here, your answer doesn't expand on that. The "simpler language" paragraph covers history that is totally unconnected to this case. The side effect issues of `++val` vs. `val++` don't apply. You have effectively said *"assuming you actually wanted to know something else, your answer is in this [other castle](http://meta.stackexchange.com/q/225370/248731)"*. The only argument you provide (extra work) is **not referenced at all in the other answer**. – jonrsharpe Jan 04 '15 at 11:43
  • @jonrsharpe it's ok, perhaps I saw a kind-of link that I was the only one to see. And I agree it's not really related. This answer gave me an impression of "it would be a big overhead for no real plus-value" but I understand it's not the real point of the author. Link removed. – Jivan Jan 04 '15 at 11:47