The possibility of an assignment operator concept for an object method

134 Views Asked by At

Let: a = 5, b = 10, and hello_world = 'Hello World'.

To my understanding: Python allows us to utilize assignment operators to prevent us from having to repeat the left operand. For example, a = a + b can be rewritten as a += b where both would return 15.

So with some Python objects it could be somewhat similar, depending on what the method being called returns.

With a string, str, or this case our string hello_world there are a multitude of methods for you to use to modify it in some way such as hello_world.lower() and sometimes I would call it to assign the variable the result of the method within. For example, hello_world = hello_world.lower() could be rewritten as something like hello_world .= lower() where both would return hello world.

Is there anything like this available in Python? Is this completely absurd or confusing to you? Curious what people think of this and/or if it exists already.

2

There are 2 best solutions below

1
On BEST ANSWER

Is there anything like this available in Python?

No

Is this completely absurd or confusing to you?

No. That said, it would be somewhat different from the existing augmented assignment operators (like +=, *=, etc.). For those operators, you can define a special magic method (__iadd__, __imul__, etc.) to implement them. A key feature of these is that, because a separate method is called, they may update the object in place. For instance, if x is a list, then x += [1, 2, 3] will actually mutate the object x rather than creating a new list.

For your proposed .= operator, it's not clear how this could work. If there were an __imeth__ operator for "augmented method assignment", what would it take as arguments? If it took the name of the method as an argument, you would need a giant if-block inside __imeth__ to decide what to do for various methods (i.e., if method == 'lower' to handle .lower() and so on). If it didn't take the name of the method as an argument, how would it know what method is being called?

More importantly, though, a fundamental feature of the existing operators is that they accept an expression as their operands. With your proposed .=, what would happen if you did x .= 3? Or x .= (foo+bar).blah()/7? Or even x .= lower (with no parentheses)? It would seem that .= would require its right-hand argument to be syntactically restricted to just a single function call (which would be interpreted as a method call). That is quite different from any existing Python operator.

It seems the only way to handle all of that would be to reduce the scope of the proposal so that it indeed only accepts a single function call on the right, and make it non-customizable, so that x .= method(...) is pure syntactic sugar for x = x.method(...). But, as described above, that is much weaker than what current augmented assignment allows, so I don't think it would be a big win.

0
On

You are thinking about augmented assignments, these are statements, and are not extensible.

Augmented assignments only cover binary operators (specifically the power, binary arithmetic, shifting and binary bitwise operators). The attribute reference syntax is not an operator, binary or otherwise. As such there is no 'attribute-operator' augmented assignment.

Note that I didn't cover the calling syntax; you are mostly talking about attributes; that you also call str.lower() is separate from the attribute lookup.

If you think this a feature sorely missed, I suggest you bring it to the Python Ideas mailinglist, where prospective new language features are discussed.

Take into account that the point of the augmented assignments is that they provide an opportunity to optimise in-place updates; they are not just syntactic sugar. For lists, for example, listobj += iterable_of_values is not the same thing as listobj = listobj + iterable_of_values, it actually executes listobj.extend(iterable_of_values) (and binds the name listobj back to listobj, which can lead to suprising behaviour. For attributes access, there is no such oppertunity; attributes return the referenced name, they can't update something in-place, unless you start abusing the descriptor protocol, which hardly lends itself to intuitive augmentation.

You may want to read the original Python Enhancement Proposal that introduced augmented assignments to the language; the rationale section especially would be required reading before you make this a proposal.