Generalised method-based augmented assisgnment

My proposal is adding === as a way to shorten: variable = variable.lower() to variable === .lower(), this is similar to += but for methods.

Should this work for potentially all methods?

Yes It is best to have this work for all methods, this should also work for multiple methods and with arguments.

Here is a code example:

Without proposal:

username = "  Davidson  "

username = username.strip()
username = username.lower()
username = username.replace("l", "1")

print(username)

With proposal:

username = "  Davidson  "

username === .strip()
username === .lower()
username === .replace("l", "1")

print(username)

Notice how both examples produce identical results, but the proposed syntax removes repetitive variable references?

That’s because my proposal is just quality of life, nothing game changing.

Does the syntax have to be ===?

No I think === is a placeholder, maybe something like @= but from here I think its up to you to decide.

How would this work?

I personally think this should be the exact same effects as doing variable = variable.lower() (or other methods), I also want to bring up the fact that some methods like .sort() don’t work on variable = variable.sort() and I propose it should stay that way for this to keep it readable and identical to the longer version.

Why would python benefit from this?

This is a simple quality of life improvement which could improve readability and improve speed of typing. Stuff like username = username.strip().lower().replace(“l”, “1”) will do the same thing in the same amount of lines but my proposal does it in fewer characters and makes it more readable.

About the person with the idea:

I am new to python (around OOP stage) so this idea will be rough around the edges, I don’t have amazing skills or anything this was just a random thought, I’m sure i have got something incorrect on the technical side, feel free to comment with suggestions for this idea or corrections. Contact me at lachlan-the-DEV github, proposed 6/11/2026.

Thanks for reading

Bye!

Alternative:

username = ("  Davidson  "
    .strip()
    .lower()
    .replace("l", "1")
)
print(username)

Chaining vertically works nicely, as long as you’re willing to parenthesize.

4 Likes

That’s a good alternative! I hadn’t considered vertical method chaining.

I think the main difference with my proposal is that it allows you to repeatedly modify an existing variable without having to restructure the original assignment.

For example, if you already have:

username = input("Username: ")

username === .strip()
username === .lower()

You can apply transformations as needed throughout your code.

Your alternative works particularly well when initially assigning a variable, whereas I think my proposal is more convenient when modifying existing variables.

Thanks for the suggestion!

I saw the main benefit in not repeating the expression. e.g.

# OP:

name_matrix[i][j] === .strip()

# vs. the current Python syntax:

name_matrix[i][j] = name_matrix[j][j].strip()

# BTW, did you notice the typo :-)

Further, chaining should be supported:

# three assignments (two of them useless)
username === .strip()
username === .lower()
username === .replace("l", "1")

# one assignment with chaining:
username === .strip().lower().replace("l", "1")

Anyway, I noticed a “fluent” style is not very welcome here.

I don’t like the use of === for this (PHP and JS have lodged quite firmly in my mind that it is a form of equality operator), but I do see the use case for

# (two typos fixed, btw. were they both intentional?)
name_matrix[i][j] = name_matrix[i][j].strip()

and it’s one I often have myself.

That said, this suggestion has come up many times and not been approved, so I’d mostly resigned myself to status quo on this one.

In particular, I believe the following syntax has been rejected:

name_matrix[i][j] .= strip()

because . is not like + and other “normal” operators: strip here is not a free function, precedence is different, and so on.

But given OP suggested name === .strip, not name === strip, I wonder about having the . in both places:

name_matrix[i][j] .= .strip()

The other reservation I have with this is it’s fine when you want to look up an attribute, but not when you want to pass it to a free function. For example:

def free_function(arg: Type) -> Type:
  ...

name_matrix[i][j] = free_function(name_matrix[i][j])

If Python ever adopts any kind of .= proposal (and that’s already a big if, as above), I’d want it to cover this use case as well.

PHP recently implemented a pipe operator proposal, after what feels like a very long time of back-and-forth on the idea (and justified, I think, since I definitely had reservations about the earlier proposals, while by contrast the latest, actually implemented one does seem very well-designed). The “pipe operator” wouldn’t by itself cover these use cases, but if it was implemented in Python^, it could overlap with this .= idea to allow use of free functions like so:

#name = name.method()
name .= .method()

#name_matrix[i][j] = name_matrix[i][j].method()
# but only calls .__getitem__(i) once
name_matrix[i][j] .= .method()

#name = free_function(name)
name .= free_function(?)

#name_matrix[i][j] = free_function(name_matrix[i][j])
# but only calls .__getitem__(i) once
name_matrix[i][j] .= free_function(?)

^IIRC the “pipe operator” has been requested here before, with similar reception to .= i.e. unlikely to happen. Regardless I do think that what PHP decided on in the end would be a good enhancement to Python too on its own merits (with a spelling change to replace PHP’s rest syntax ... with Python’s rest syntax *, of course). I did previously consider posting it here when I read about it, but figured it wouldn’t be worth it; it should definitely be a separate thread to this one if there’s renewed interest, though.

If such an idea were to be supported, I’d rather see “.=” being used as follows:

username = "  Davidson  "

username .= strip()
username .= lower()
username .= replace("l", "1")

However, one can currently design classes that support chaining, with a notation similar to that shown by @Rosuav , so it is hard to justify the introduction of a special syntax for this purpose.

1 Like

Only one was intentional. I corrected the other one. Thank you for spotting the error.

@= is used for augmented matrix multiplication assignment.

I don’t think this or any of the variants so far suggested will lead to more readable programs. I don’t think typing the same variable name twice is a problem that needs to be solved, let alone by introducing syntax, and __getitem__/__setitem__ lookups aren’t more special.

If typos in a sequence of lookup keys is a problem, helper functions are not difficult to write:

def modify_element(operation, container, *keys):
    while len(keys) > 1:
        key, *keys = keys
        container = container[key]
    key = keys[0]
    container[key] = operation(container[key])

modify_element(str.strip, name_matrix, i, j)
1 Like

While I generally agree many Ideas threads are better tackled by using helper functions, this particular one is, objectively, unviable for those (like me) who use strict typing and code assist.

An additional subjective argument is that neither of these are Pythonic:

name_matrix[i][j] = free_function(name_matrix[i][j])

modify_element(free_function, name_matrix, i, j)

because the intention is “I want to do a thing with a particular array element”. The first repeats itself, and the second does not look like you’re accessing an array element.

Meanwhile,

name_matrix[i][j] .= free_function(?)

if this was valid syntax today and did what I suggested it might do, I would argue is Pythonic^, because it’d be doing what it said: it’s doing a thing with a particular array element, and the thing it’s doing is calling free_function with the current value and updating it to have the result of that function call.

^or at least, much more Pythonic than the two earlier examples.

I disagree that name_matrix[i][j] = free_function(name_matrix[i][j]) is unpythonic. Repeating an identifier is not an antipattern, it’s just part of programming.