SyntaxError: cannot use assignment expressions with attribute

Is there a reason why this is not allowed? return (self.mode := self.mode_valid(mode))

On 2023-10-09 02:17, Dom Grigonis wrote:
Is there a reason why this is not allowed?
return (self.mode := self.mode_valid(mode))
The principal use-case for the operator is in conditions, for example: if m := re.match(pattern_1, string): ... elif m := re.match(pattern_2, string): ... else: ... or: while line := file.readline(): ... Do you have a convincing argument that it should be expanded from a simple name? Having: self.mode = self.mode_valid(mode) return self.mode isn't too bad.

No, not bad at all. But to me, being able to use walrus would be convenient. ——— This nuance can also be encountered in “principal use-case”. E.g.: class A: def func(self): while (self.a := 1) < 5: self.a += 1 return self.a A().func() Could be useful in iterator protocol implementations, where/or_where state is managed with property setters managing objects that implement custom `__iadd__`, etc or just simply convenience as in my former example. Same argument as for “walrus” operator itself - convenient feature. Or is there more to it? ——— I was actually surprised that this didn’t work - I thought that this operator is a literal composite of assignment and “retriever", rather than having it’s own restrictive logic. Could be a reason for it, maybe to avoid some undesirable mis-usage. But I can’t see it. Any issues arising from such construct would be the same issues as for: expr = 1 expr This could be an actual assignment + retrieval of left-hand-side, then it would work generically for all constructs, such as: a()[‘a'] := 1 a().attr := 1 If walrus currently has its own specific logic, this would integrate it nicely into assignment operator. Then it would benefit automatically from any language extension that makes use of it. Or is it already it, just with added restrictions? All in all, I think would be a generalisation of a convenience feature, which doesn’t invent anything new, but extends its convenience to more general application. These are my thoughts, whether it’s worthwhile and sensible - I have no idea. If it doesn’t break anything, doesn’t have any undesirable side effects and community likes it, then could be a good addition. Regards, DG P.S. Deferred evaluation will be able to handle this one too

Dom Grigonis writes:
Not sure what you're getting at here, that's an infloop. Did you mean something like this: class A: def func(self): while (self.a := self.a += 1) < 5: pass return self.a I'm pretty sure that exact idiom, modeled on the C "copy string" idiom void strcpy(char *s, char *t) { while (*t++ = *s++) would generally be considered unpythonic, but I suppose some people might like it if instead of pass you had a real suite there. I think it's a real "meh" use case, since in most cases it can be rewritten class A: def func(self): while self.a < (5 - 1): # expression to make the # transformation clear self.a += 1 return self.a and you save a couple characters and at most one line (none in the case you present).
Same argument as for “walrus” operator itself - convenient feature. Or is there more to it?
There's more to it. The loop and a half construct, where you execute the body of the loop once outside the loop for some reason is widely considered a really big wart (DRY failure). The walrus allows us to eliminate most of those. On the other hand, an assignment and a return statement are two different things; it's not a DRY viotion to have the same identifier in both.
This is a common practice in Python development. Try a little bit of a new idea, avoid engineering, and expand later if that seems useful too.
If it doesn’t break anything, doesn’t have any undesirable side effects and community likes it, then could be a good addition.
"Community likes it" is a null predicate, very hard to verify in edge cases. When the support in the community is strong enough that "community likes it" is common knowledge, it's always the case that there are objective reasons why it's a good thing. All additions have a 0 * infinity cost: a negligible cost of learning (for one user) times *all* the users. Other projects feel differently about it, but Python tends to be quite conservative about additions. Steve

Dom Grigonis writes:
It *does* work with a while loop, just not that one. See below. The problem is that you're writing new code full of trash you don't need to explain the concept. Keep these examples as simple as possible. For example, my "pass" example is too simple if you want to show how the walrus can save typing because it doesn't save any lines of code; you need something a little more complicated to demonstrate that saving. In the progress of any proposal to acceptance, at some point someone is going to say, "I see that it works and solves a theoretical problem, but who would ever use it?" At that point you go into a large body of code such as the Python standard library or numpy to find realistic examples. But that's old code, and only needed to demonstrate actual utility.
That's not the question though. The question is are those examples themselves frequently useful. And that's when you go find them in the stdlib.
The problem is code like this: with open("a_file") as f: while (line := f.readline()) if check(line): process(line) else: break There is no way to do that without an assignment, and without the walrus you need an assignment before the while, and the same assignment within the loop body. Is that a big deal? No. In fact, I have never used the walrus operator in anger, nor wanted to. I'm just as happy to write with open("a_file") as f: line = f.readline() while (line) if check(line): process(line) else: break line = f.readline() But some people find loop-and-a-half extremely ugly, and while I differ on "extremely", I can't deny that it's ugly. You *could* do this for small files with with open("a_file") as f: lines = f.readlines() for (line in lines): if check(line): process(line) else: break but that's not possible with an infinite iterable, undesireable for most non-file streams, etc. Re "simple examples", see why I used the "if check()" stuff? If I wasn't going to talk about infinite iterables and pausing external streams, that would just be (potentially wrong!) complexity that doesn't help explain anything. Steve

I just want to note that this is just a gentle suggestion/observation, in case this wasn’t done yet. I am not pushing this. —— All good points, thank you. —— Why would this not be a good option? 1 extra line compared to walrus, but no DRY issue. with open(“fn") as f: while True: line = f.readline() if line and check(line): process(line) else: break DG

The fact that it is not allowed is nothing to do with the 'return'. You *can* write return (x := x+1) What you can't (at present) do is use the walrus operator with an attribute: x = (self.a := self.a + 1) # SyntaxError I too have found times when this would be convenient. As Stephen says, Python often adds new features conservatively, then extends them later if/when it seems desirable. This happened with the '@' decorater: originally it came with all manner of restrictions, but eventually they were removed. IMO this was a good thing because it made the language more uniform, meaning you didn't have to remember what was allowed and what wasn't; so I hope the same will happen with the walrus operator. Best wishes Rob Cliffe On 09/10/2023 02:17, Dom Grigonis wrote:

On 2023-10-09 02:17, Dom Grigonis wrote:
Is there a reason why this is not allowed?
return (self.mode := self.mode_valid(mode))
The principal use-case for the operator is in conditions, for example: if m := re.match(pattern_1, string): ... elif m := re.match(pattern_2, string): ... else: ... or: while line := file.readline(): ... Do you have a convincing argument that it should be expanded from a simple name? Having: self.mode = self.mode_valid(mode) return self.mode isn't too bad.

No, not bad at all. But to me, being able to use walrus would be convenient. ——— This nuance can also be encountered in “principal use-case”. E.g.: class A: def func(self): while (self.a := 1) < 5: self.a += 1 return self.a A().func() Could be useful in iterator protocol implementations, where/or_where state is managed with property setters managing objects that implement custom `__iadd__`, etc or just simply convenience as in my former example. Same argument as for “walrus” operator itself - convenient feature. Or is there more to it? ——— I was actually surprised that this didn’t work - I thought that this operator is a literal composite of assignment and “retriever", rather than having it’s own restrictive logic. Could be a reason for it, maybe to avoid some undesirable mis-usage. But I can’t see it. Any issues arising from such construct would be the same issues as for: expr = 1 expr This could be an actual assignment + retrieval of left-hand-side, then it would work generically for all constructs, such as: a()[‘a'] := 1 a().attr := 1 If walrus currently has its own specific logic, this would integrate it nicely into assignment operator. Then it would benefit automatically from any language extension that makes use of it. Or is it already it, just with added restrictions? All in all, I think would be a generalisation of a convenience feature, which doesn’t invent anything new, but extends its convenience to more general application. These are my thoughts, whether it’s worthwhile and sensible - I have no idea. If it doesn’t break anything, doesn’t have any undesirable side effects and community likes it, then could be a good addition. Regards, DG P.S. Deferred evaluation will be able to handle this one too

Dom Grigonis writes:
Not sure what you're getting at here, that's an infloop. Did you mean something like this: class A: def func(self): while (self.a := self.a += 1) < 5: pass return self.a I'm pretty sure that exact idiom, modeled on the C "copy string" idiom void strcpy(char *s, char *t) { while (*t++ = *s++) would generally be considered unpythonic, but I suppose some people might like it if instead of pass you had a real suite there. I think it's a real "meh" use case, since in most cases it can be rewritten class A: def func(self): while self.a < (5 - 1): # expression to make the # transformation clear self.a += 1 return self.a and you save a couple characters and at most one line (none in the case you present).
Same argument as for “walrus” operator itself - convenient feature. Or is there more to it?
There's more to it. The loop and a half construct, where you execute the body of the loop once outside the loop for some reason is widely considered a really big wart (DRY failure). The walrus allows us to eliminate most of those. On the other hand, an assignment and a return statement are two different things; it's not a DRY viotion to have the same identifier in both.
This is a common practice in Python development. Try a little bit of a new idea, avoid engineering, and expand later if that seems useful too.
If it doesn’t break anything, doesn’t have any undesirable side effects and community likes it, then could be a good addition.
"Community likes it" is a null predicate, very hard to verify in edge cases. When the support in the community is strong enough that "community likes it" is common knowledge, it's always the case that there are objective reasons why it's a good thing. All additions have a 0 * infinity cost: a negligible cost of learning (for one user) times *all* the users. Other projects feel differently about it, but Python tends to be quite conservative about additions. Steve

Dom Grigonis writes:
It *does* work with a while loop, just not that one. See below. The problem is that you're writing new code full of trash you don't need to explain the concept. Keep these examples as simple as possible. For example, my "pass" example is too simple if you want to show how the walrus can save typing because it doesn't save any lines of code; you need something a little more complicated to demonstrate that saving. In the progress of any proposal to acceptance, at some point someone is going to say, "I see that it works and solves a theoretical problem, but who would ever use it?" At that point you go into a large body of code such as the Python standard library or numpy to find realistic examples. But that's old code, and only needed to demonstrate actual utility.
That's not the question though. The question is are those examples themselves frequently useful. And that's when you go find them in the stdlib.
The problem is code like this: with open("a_file") as f: while (line := f.readline()) if check(line): process(line) else: break There is no way to do that without an assignment, and without the walrus you need an assignment before the while, and the same assignment within the loop body. Is that a big deal? No. In fact, I have never used the walrus operator in anger, nor wanted to. I'm just as happy to write with open("a_file") as f: line = f.readline() while (line) if check(line): process(line) else: break line = f.readline() But some people find loop-and-a-half extremely ugly, and while I differ on "extremely", I can't deny that it's ugly. You *could* do this for small files with with open("a_file") as f: lines = f.readlines() for (line in lines): if check(line): process(line) else: break but that's not possible with an infinite iterable, undesireable for most non-file streams, etc. Re "simple examples", see why I used the "if check()" stuff? If I wasn't going to talk about infinite iterables and pausing external streams, that would just be (potentially wrong!) complexity that doesn't help explain anything. Steve

I just want to note that this is just a gentle suggestion/observation, in case this wasn’t done yet. I am not pushing this. —— All good points, thank you. —— Why would this not be a good option? 1 extra line compared to walrus, but no DRY issue. with open(“fn") as f: while True: line = f.readline() if line and check(line): process(line) else: break DG

The fact that it is not allowed is nothing to do with the 'return'. You *can* write return (x := x+1) What you can't (at present) do is use the walrus operator with an attribute: x = (self.a := self.a + 1) # SyntaxError I too have found times when this would be convenient. As Stephen says, Python often adds new features conservatively, then extends them later if/when it seems desirable. This happened with the '@' decorater: originally it came with all manner of restrictions, but eventually they were removed. IMO this was a good thing because it made the language more uniform, meaning you didn't have to remember what was allowed and what wasn't; so I hope the same will happen with the walrus operator. Best wishes Rob Cliffe On 09/10/2023 02:17, Dom Grigonis wrote:
participants (4)
-
Dom Grigonis
-
MRAB
-
Rob Cliffe
-
Stephen J. Turnbull