[Python-ideas] A real life example of "given"

Neil Girdhar mistersheik at gmail.com
Wed May 30 22:50:46 EDT 2018


On Wed, May 30, 2018 at 9:02 PM Steven D'Aprano <steve at pearwood.info> wrote:

> On Thu, May 31, 2018 at 10:05:33AM +1000, Chris Angelico wrote:
> > On Thu, May 31, 2018 at 9:53 AM, Steven D'Aprano <steve at pearwood.info>
> wrote:
> > >> There is no nice, equivalent := version as far as I can tell.
> > >
> > > Given (pun intended) the fact that you only use transformed_b in a
> > > single place, I don't think it is necessary to use := at all.
> > >
> > > z = {a: transform(b) for b in bs for a in as_}
> > >
> > > But if you really insist:
> > >
> > > # Pointless use of :=
> > > z = {a: (transformed_b := transform(b)) for b in bs for a in as_}
> > >
> >
> > That's the subtlety of the 'given' usage here. You fell for the same
> > trap I did: thinking "it's only used once".
>
> But it is only used once. I meant once per loop.
>
> It isn't used in the "for a in as_" inner loop, there's no "if
> transformed_b" condition, and it only is used once in the key:value part
> of the comprehension.
>
>
> > Actually, what he has is equivalent to:
> >
> > z = {a: tb for b in bs for tb in [transform(b)] for a in as_}
>
> Which also uses tb only once, making it a Useless Use Of Assignment.
>
> (I assume we're not calling transform() for some side-effect, like
> logging a message, or erasing your hard drive.)
>
>
> > which means it evaluates transform(b) once regardless of the length of
> > as_.
>
> Ah yes, I see what you mean. Expanded to a loop:
>
>     for b in bs:
>         tb = transform(b)
>         for a in as_:
>             z[a] = tb
>
>
> It's a little ugly, but there's a trick I already use today:
>
> py> [x+y for x in "abc" if print(x) or True for y in "de"]
> a
> b
> c
> ['ad', 'ae', 'bd', 'be', 'cd', 'ce']
>
> So we can adapt that to assignment instead of output:
>
> # Don't do this!
> z = {a: tb for b in bs if (tb := transform(b)) or True for a in as_}
>
> But I wouldn't do that. If I'm concerned about the call to transform
> (because it is super expensive, say) then I set up a pipeline:
>
> tbs = (transform(b) for b in bs)  # or map(transform, bs)
> z = {a: tb for tb in tbs for a in as_}
>
> The first generator comprehension can be easily embedded in the other:
>
> z = {a: tb for tb in (transform(b) for b in bs) for a in as_}
>
> This makes it super-obvious that transform is called for each b, not for
> each (b, a) pair, it works today, and there's no assignment expression
> needed at all.
>
> Assignment expressions should not be about adding yet a third way to
> solve a problem that already has a perfectly good solution! ("Expand to
> a loop statement" is not a *perfectly* good solution.) To showcase
> assignment expressions, we should be solving problems that don't have a
> good solution now.
>
> I'm still not convinced that Neil's "given" example will even work (see
> below) but *if he is right* that it does, perhaps that's a good reason
> to prefer the simpler := assignment expression syntax, since we're
> less likely to use it in confusing ways.
>
>
> > But it's really REALLY not obvious.
>
> But is it even legal?
>
> As I understand it, "given" is an expression, not an addition to
> comprehension syntax. In that case, I don't think Neil's example will
> work at all, for reasons I've already stated.
>
> If that's not the case, then until somebody tells me what this new
> comprehension syntax means, and what it looks like, I have no idea what
> is intended.
>
> Which of these can we write, and what do they do?
>

Great question.  The trick is to just write them as a sequence of
statements without changing the order except to put the expression last.


>
>     [expression given name=something for x in seq]
>

retval = []
name = something
for x in seq:
    retval.append(expression)
return retval

>
>     [expression for x given name=something in seq]
>

this one doesn't make sense.

    [expression for x in seq given name=something]
>
>
retval = []
for x in seq:
    name = something
    retval.append(expression)
return retval


>     [expression for x in seq if given name=something condition]
>
> this one doesn't make sense.


>     [expression for x in seq if condition given name=something]
>
> retval = []
for x in seq:
    if condition:
        name = something
        retval.append(expression)
return retval

and of course, the original proposal

expression given name=something

means:

name = something
retval = expression
return retval


>
> --
> Steve
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "python-ideas" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/python-ideas/keaR3FudcwQ/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> python-ideas+unsubscribe at googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180530/7566d63a/attachment.html>


More information about the Python-ideas mailing list