'.=' assignment

I just got an idea for a new assignment opoerator, .=. .= would assign an object to one of it’s fields. So like this:

object.= x
# Same as this:
object = object.x

object.= method()
# Same as this:
object = object.method()

object.= a.b.c
# Same as this:
object = object.a.b.c

I think this would be very useful and it would not be that hard to implement. I do not know what it would be called, or maybe if = . would be better, but this feature would be good.

1 Like

What would it be useful for? I don’t know that I’ve ever wanted to do this, to be honest. Can you provide some examples of code where you’d use this?

13 Likes

This would also not work with type checkers, which expect the type of a name to remain consistent.

9 Likes

Also the syntax is cryptic.

3 Likes

15 posts were split to a new topic: Changing the type of a name after first usage

Maybe a bad idea, but there are SOME uses. I just like concise code and code with little repetition.

We all do! There very well might be some uses, but you haven’t shared what they are.

In my experience, if I have some object foo and it only has one attribute bar that I care about, then I look to refactor the code so that I’m just passing around bar in the first place. If foo has multiple attributes, then I probably don’t want to assign foo = foo.bar because a) that will be confusing later and b) I’ve lost access to the other attributes, which I might end up needing.

So I don’t personally see a use-case for this, certainly not enough of one to justify new syntax. But maybe it exists?

i = i+1 or x = x - delta are common iteration operations which leave the type of the name the same. Rebinding a name to an attribute of the object formerly bound is so rare that I cannot remember ever seeing an instance thereof. It can and should be spelled out.

Linked list iteration: node .= next

Binary tree traversal: node .= left (or right)

String normalization: word .= lower()

13 Likes

Honestly, those all look like NameErrors waiting to happen. I don’t see any improvement (other than character count) over the explicit code

node = node.next
node = node.left
word = word.lower()
4 Likes

String operations;

# fix microsoft nonsense
string = string.replace(r"\r\n", r"\n")
# escape the frobblenob
string = string.replace("##", "#!<#")

Path (from pathlib) operations;
etc.

There are lots of things similar to this, where it would be nice.
There’s also linked lists, like with frame = frame.f_back.

Also, it would be semantically nice to have an __iN__ operator for every __N__, operator instead of just some of them.

“Subscription, slicing, call, attribute reference” are expression formations of equal high precedence, but ‘.’ is not an operator in the way that ‘+’, etc are. In x += y, x and y are both syntax names bound to objects. The implementation is x.__iadd__(y). In node .= next, next not bound to anything and would be name error. The parallelism fails. For indexing, n in a proposed seq []= n would at least be bound to something. Besides the problem of argument structure not being an object, the need for func ()= <args>rebinding would be super rare.

4 Likes

I personally don’t really like this, because the RHS can’t be an arbitrary expression, so it’s not really analogous to other “augmented assignment operators”. For example, what does a .= b + c mean? Presumably it’d be a SyntaxError.

5 Likes

Seems quite specialised - this might be useful when you’re doing certain kinds of recursion, but apart from that I can’t see it being used generally.

1 Like

If it could plausibly mean

a = a.b + a.c

it would need to be a runtime error, probably an AttributeError.

1 Like

Too niche use case, and the syntax is confusing.

1 Like

You can’t have an arbitrary expression on the right-hand side of the . operator either-- a . (b + c) is a syntax error. It wouldn’t make sense to allow arbitrary expressions for one but not the other.

Really, I only want this operator if we could have []=, ()=, and maybe unary ~=, -= and +=.
It would be conceptually much nice if each __N__ operator had an __iN__. Otherwise,
We’d still have the mismatch that currently exists, and not much would change (although having
the .= operator would still be nice to have for some usecases).

2 Likes

Someone sort this one out for me :slight_smile:


func = None

def func(func):
    global func
    func ()= func
   
func ()= func
2 Likes

This bit does nothing because func is reassigned later.

func = None

For the rest of it, I’ve changed the variable names to make it more clear what’s happening here.

def global_func(arg_func): # `arg_func` is unused here

    # In the original, this shadowed the argument.  The
    # `global` declaration isn't necessary now that I've
    # changed the names, but it's here anyway.
    global global_func

    # `global_func = global_func.__icall__(global_func)`
    global_func ()= global_func


# `global_func = global_func.__icall__(global_func)`
global_func ()= global_func

I hope that helps :slight_smile:

1 Like

And presumably after executing that, global_func is once again None, because it doesn’t return anything. Or perhaps it’s just a recursion error.