[Tutor] use of assignment expression

Mats Wichmann mats at wichmann.us
Sun Aug 16 19:44:23 EDT 2020


On 8/16/20 4:31 PM, Alan Gauld via Tutor wrote:
> On 16/08/2020 14:55, Manprit Singh wrote:
> 
>> # Program to find smallest n digit number divisible by a number x
>> n = 5
>> x = 83
>> if (no := (10**(n-1) % x)) == 0:
>>     print(10**(n-1))

Since no is never used, why do this (was something missing from your
example)? Plus, no probably isn't getting the value you want: it will be
True or False.

>> else:
>>     print((mx := (10**(n-1) + x)) - (mx % x))
>>
>> The answer is 10043, which is the right answer . Just need to know if the
>> way of using the assignment expression (2 times in the above example is
>> efficient or not.),
> 
> Efficiency is not really the issue.
> There are a few marginal cases where inline assignment is convenient
> (and your else print expression is an example) but in most cases you
> are simply trading a small amount of space saving with a significant
> hit in readability and debuggability (is that a word?).
> 
> Even in the else expression any improvement in efficiency is not
> likely to be high enough to sacrifice readability. Consider the alternative:
> 
> mx = 10**(n-1) + x
> print( mx - (mx % x))
> 
> Is that one extra line really going to hurt so much?
> 
>> What i feel is the usage of assignment expressions is reducing the
>> readability of the code written above  . Need your guidance.
> 
> I would agree. And it makes it much harder to debug since you
> cannot examine the value before executing the if statement.

It makes sense if you're immediately going to redo the computation.
Which you do, so it's a /candidate/.  There are either two or three
times you might compute 10**(n-1). As written you would save one, in the
else case - at the cost of having to worry about evaluation order: did
that line risk the mx on the right side of the := being undefined or
some previous value, or is it going to pick up the first part of the
expression? I'd opine that here the cost isn't worth it, as Alan does.

The idea would be to structure the code, walrus operator or not, so you
don't have to repeat a computation and in this specific case it's
probably best to avoid it by splitting instead:

ex = 10 ** (n - 1)
if not ex % x:
    print(ex)
else:
    print(ex + x - ((ex + x) % x))

(untested, I've probably mangled it)

The walrus operator does have real uses. I haven't had a chance to use
it much because I'm mainly working on a codebase that must promise
support back to Python 3.5 (we just got off 2.7, yay!) but the other one
that works for me is when you're looping over a resource that exhausts -
a generator, a file, etc. - you want to test the next item, and then
possibly use it in the body, but testing it already consumed it, so that
doesn't work without :=, or making a more awkward loop with the first
read outside, and the next read following the use inside the loop as
we've been used to doing.



More information about the Tutor mailing list