[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Python-Dev] Call for prudence about PEP-572

> [Tim]
> > When I was staring at my code, I never mentioned the very first
> > plausible use I bumped into (in code I was actively working on at the
> time):
> >
> > while not probable_prime(p := randrange(lo, hi)):
> >       pass
> > # and now `p` is likely a random prime in range

{Terry Reedy]
> As long as lo excludes 0:
> while p := randrange(lo, hi) and not probable_prime(p):
>      continue
I can see how someone might prefer this stylistically, but it is buggy.
> If this is contained in a function (very likely) and lo could be <= 0,
> because it is either passed in or calculated, 0 could be passed on a
> likely prime!

I never write code that uses "and" relying on that context-specific data
constraints "guarantee" the LHS is always true.  That combines a delicate
precondition with "a trick".  Dreadful.

I won't even write it this way, which keeps "the trick" but eliminates the
hidden data assumption:

while [p := randrange(lo, hi)] and not probable_prime(p):

A singleton list is always truthy, so at least now it makes no assumptions
about the value bound to `p`.

I could be paid to write it this way, but most employers couldn't afford to
pay enough to do it twice ;-) :

while [(p := randrange(lo, hi)), not probable_prime(p)][-1]:

That always works and doesn't rely on "a trick", but is ugly, obscure, and

> I never mentioned it because I expected it would annoy people on 3(!)
> > counts:
> >
> > - assigning in a function call
> This is a style preference that people can and will disagree on.  In any
> case, I think correctness trumps beauty, just as it trumps speed.

All else being equal (and, yup, correctness is more equal than the others),
I like to push assignments "to the left" as much as possible.

> > - reducing the loop body to `pass`
> I fixed that ;-).  'continue' better expresses the 'try again' part of
> English versions, such as "While the trial value is not acceptable, try
> again."

Thanks!  Now that you mention it (it had not occurred to me), I like
`continue` much better than `pass` here too.

> - using the binding long after the loop ended

The same is true for the current 4-line loop and a half.
> while True:
>      p = randrange(lo, hi)
>      if probable_prime(p):
>          break  # p used somewhere else

Sure.  But this PEP _started_ with a fancier model wherein the language
would magically limit the scope of assignment targets in these
block-opening tests.  That was eventually removed, but I'm sure we'll see
"style guides" demanding that it "should" never be used unless the target
is in fact never referenced (at least not before re-binding) after the
associated block ends.

It's been mildly surprising to me to see how often that _is_ the case in
real code.  But, as in the example above, I won't be following such a rule

> Indeed, for those reasons it wasn't "an obvious" win to me - or an
> > obvious loss.  So I just moved on.
> >
> > However, after staring at hundreds of other cases, it does strike me as
> > "a small win" today - my brain cells have rewired to recognize more ":="
> > patterns at a glance.
> >
> > Whether that's a good thing or not I don't know, but it is a real thing
> ;-)

> I must admit that I too am already more comfortable with := now than I
> was originally.

The stories about its uncanny ability to destroy entire projects with a
single use may have been exaggerated ;-)

But, ya, I've tried playing with it much more than most so far, and my bar
for "obvious little win" has lowered.  Not much, though, and it seems to
have bottomed out with that example.

So, in the end, I expect I'll use it as sparingly - and gratefully! - as in
all the other languages I've used with assignment expressions.

Next project:  rehabilitate the much-maligned GOTO statement ;-)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20180707/8092f381/attachment.html>