[Python-ideas] PEP 572: Assignment Expressions (post #4)

Jacco van Dorp j.van.dorp at deonet.nl
Thu Apr 12 08:22:28 EDT 2018


2018-04-12 13:28 GMT+02:00 Kirill Balunov <kirillbalunov at gmail.com>:
>
>
> 2018-04-12 12:48 GMT+03:00 Jacco van Dorp <j.van.dorp at deonet.nl>:
>>
>> Wouldn't these local name bindings make the current "as" clause of
>> "with f(x) as y" completely obsolete ?
>>
>> It's probably good to know my background, and my background is that I
>> know completely nothing of the implementation, im only junior software
>> engineer, and python was my first programming experience, and still
>> the one I have by far the most experience with.
>>
>> To me, the entire proposal sounds mostly like an expansion of the as
>> syntax as we know it from "with". There will be no difference between:
>>
>> with open(filename) as f:
>>     // code
>>
>> and
>>
>> with f  := open(filename):
>>     // code
>>
>> or at least as far as I can see. (that is, if := will be allowed in
>> the with statement, and it sounds like it will ?)
>>
>
> Thank you Jacob! I do not know if I understood correctly how you understand
> what is happening here. But you are just demonstrating my fears about this
> proposal...
>
> with f  := open(filename):
>
> This will be only valid if the returned object of (f := open(filename))
> defines __enter__ and __exit__ methods ( Nevertheless, in this situation it
> is so). But in other cases it will raise an error. Generally  `with name  :=
> expr` is not equivalent to `with expr as name:`. In another places, for
> example, `except` clause `f := something` is valid only if the returned type
> is an object, which inherit from BaseException. So in this two situations,
> in my opinion, it will not be used too much.
>
> Yours example under current proposal should look like  `with open(
> full_file_path := os.path.join(path, filename) ) as f:`.
>
> With kind regards,
> -gdg

No, it will not raise an error to replace all these "as" usages with
name binding, if we choose operator priority right.

Even if we consider "with (y := f(x))", the f(x) the with gets is the
same as the one bound to the name - that's the point of the binding
expression. The only difference seems to be whether the name binding
is done before or after the __enter__ method - depending on operator
priority (see below).

I've looked through PEP 343, contextlib docs (
https://docs.python.org/3/library/contextlib.html ), and I couldn't
find a single case where "with (y := f(x))" would be invalid.

The only difference I can think of is objects where __enter__ doesn't
return self. Inexperienced programmers might forget it, so we're
giving them the "as y" part working instead of binding y to None.
There might be libraries out there that return a non-self value from
__enter__, which would alter behaviour. I honestly can't imagine why
you might do that tho.

And this could be entirely solved by giving "with" a higher priority
than "as". Then if "as" was used instead of ":=", you could just drop
"as" as part of the with statement, and it'd work the exact same way
everyone's used to.

And it's basically the same with "except x as y"; If except gets a
higher priority than as, it'd do the same thing(i.e., the exception
object gets bound to y, not the tuple of types). At least, that's what
it'd look like from outside. If people'd complain "but the local
binding does different behind except", you explain the same story as
when they would ask about the difference between + and * priority in
basic math - and they'd be free to use parenthesis as well if they
really want to for some reason i'm unable to comprehend.

except (errors := (TypeError, ValueError)) as e:  # Or of course:
except ( (TypeError, ValueError) as errors ) as e:
    logger.info(f"Error {e} is included in types: {errors}")


Where it all comes together is that if as is chosen instead of :=, it
might just be far easier to comprehend for people how it works. "same
as in with" might be wrong technically, but it's simple and correct
conceptually.

Note: I'm talking about operator priority here as if with and except
return anything - which I know they don't. That probably complicates
it a lot more than it sounds like what I've tried to explain my
thoughts here, but I hope I made sense. (it's obvious to me, but well,
im dutch..(jk))

Jacco


More information about the Python-ideas mailing list