Re: Python-ideas Digest, Vol 166, Issue 76
On Fri, Sep 18, 2020 at 2:13 AM Alexis Masson<a.masson555@ntymail.com> wrote:
This, in addition with locals().update(_), feels much better to me. Furthermore, it would allow other string-like classes, such as bytes or bytearray, to use that feature.
But locals().update() isn't a supported operation, except in the situation where locals() is globals(). So what you're suggesting would work fine in the REPL but not in any production usage.
ChrisA That surprises me. I put a quick test to check :
def f() : print(locals()) locals().update(dict(a=3)) print(locals())
f() prints :
================= RESTART: ****/test.py ================ {} {'a': 3}
So maybe the specs don't force it, but under the current implementation, it seems to work.
I agree that it's bad practice anyway; a correct solution to the original question might surely involve something akin to :for key, value in parsed.items() :
for key, value in parsed.items() :
exec(f"{key} = {value}")
I like the idea of needing to format a string in the process of parsing another ;) Anyway, back on topic !
On Thu, Sep 17, 2020 at 8:33 PM Alexis Masson <a.masson555@ntymail.com> wrote:
On Fri, Sep 18, 2020 at 2:13 AM Alexis Masson <a.masson555@ntymail.com> <a.masson555@ntymail.com> wrote:
This, in addition with locals().update(_), feels much better to me. Furthermore, it would allow other string-like classes, such as bytes or bytearray, to use that feature.
But locals().update() isn't a supported operation, except in the situation where locals() is globals(). So what you're suggesting would work fine in the REPL but not in any production usage.
ChrisA
That surprises me. I put a quick test to check :
def f() : print(locals()) locals().update(dict(a=3)) print(locals())
f()
prints :
================= RESTART: ****/test.py ================ {} {'a': 3}
So maybe the specs don't force it, but under the current implementation, it seems to work.
No it doesn't, try `print(a)`.
I agree that it's bad practice anyway; a correct solution to the original question might surely involve something akin to :for key, value in parsed.items() :
for key, value in parsed.items() :
exec(f"{key} = {value}")
This has the same problem for the same underlying reasons, it won't work in a function either.
OK, I admit defeat, you're indeed right. I thought it worked, but it doesn't; well, I've learned something today, thank you for that ! However, I stand firm on my original idea (just the same as what Brendan Barnwell wrote earlier) : I still think returning a dict is the best way to implement the proposed feature, among others because potentially popping a bunch of variables in the local namespace is clumsy, if not dangerous. As for making it a str method, I feel like what we're doing is the same kind of interaction between strings as in str.split, and should therefore be treated the same way. Regards, Alexis Le 17/09/2020 à 20:38, Alex Hall a écrit :
On Thu, Sep 17, 2020 at 8:33 PM Alexis Masson <a.masson555@ntymail.com <mailto:a.masson555@ntymail.com>> wrote:
On Fri, Sep 18, 2020 at 2:13 AM Alexis Masson<a.masson555@ntymail.com> <mailto:a.masson555@ntymail.com> wrote:
This, in addition with locals().update(_), feels much better to me. Furthermore, it would allow other string-like classes, such as bytes or bytearray, to use that feature.
But locals().update() isn't a supported operation, except in the situation where locals() is globals(). So what you're suggesting would work fine in the REPL but not in any production usage.
ChrisA
That surprises me. I put a quick test to check :
def f() : print(locals()) locals().update(dict(a=3)) print(locals())
f()
prints :
================= RESTART: ****/test.py ================ {} {'a': 3} >>>
So maybe the specs don't force it, but under the current implementation, it seems to work.
No it doesn't, try `print(a)`.
I agree that it's bad practice anyway; a correct solution to the original question might surely involve something akin to :for key, value in parsed.items() :
for key, value in parsed.items() :
exec(f"{key} = {value}")
This has the same problem for the same underlying reasons, it won't work in a function either.
On Fri, Sep 18, 2020 at 4:32 AM Alexis Masson <a.masson555@ntymail.com> wrote:
On Fri, Sep 18, 2020 at 2:13 AM Alexis Masson <a.masson555@ntymail.com> wrote:
This, in addition with locals().update(_), feels much better to me. Furthermore, it would allow other string-like classes, such as bytes or bytearray, to use that feature.
But locals().update() isn't a supported operation, except in the situation where locals() is globals(). So what you're suggesting would work fine in the REPL but not in any production usage.
ChrisA
That surprises me. I put a quick test to check :
def f() : print(locals()) locals().update(dict(a=3)) print(locals())
f()
prints :
================= RESTART: ****/test.py ================ {} {'a': 3}
So maybe the specs don't force it, but under the current implementation, it seems to work.
It isn't supported, which means that sometimes it'll appear to work, but you can't depend on it. For instance:
def f(): ... print(locals()) ... locals().update({"a": 3}) ... print(a) ... f() {} Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in f NameError: name 'a' is not defined
The only time you can safely mutate locals() is when you're at top level and it's the same as globals(). Plus, assignment might not even affect locals(), and it'd be extremely weird if your parse operation couldn't assign to something declared global :) ChrisA
On Thu, Sep 17, 2020 at 8:49 PM Chris Angelico <rosuav@gmail.com> wrote:
The only time you can safely mutate locals() is when you're at top level and it's the same as globals().
It's safe in class definitions, right? At least in CPython it seems to work. I've done that a few times, most recently to dynamically generate enum members.
On Fri, Sep 18, 2020 at 4:55 AM Alex Hall <alex.mojaki@gmail.com> wrote:
On Thu, Sep 17, 2020 at 8:49 PM Chris Angelico <rosuav@gmail.com> wrote:
The only time you can safely mutate locals() is when you're at top level and it's the same as globals().
It's safe in class definitions, right? At least in CPython it seems to work. I've done that a few times, most recently to dynamically generate enum members.
Hmm. I'm not actually sure there, but my belief is that it still isn't guaranteed - it just happens to work in current versions of CPython. locals() Return a dictionary containing the current scope's local variables. NOTE: Whether or not updates to this dictionary will affect name lookups in the local scope and vice-versa is *implementation dependent* and not covered by any backwards compatibility guarantees. ChrisA
On Thu, 17 Sep 2020 at 20:07, Chris Angelico <rosuav@gmail.com> wrote:
On Fri, Sep 18, 2020 at 4:55 AM Alex Hall <alex.mojaki@gmail.com> wrote:
On Thu, Sep 17, 2020 at 8:49 PM Chris Angelico <rosuav@gmail.com> wrote:
The only time you can safely mutate locals() is when you're at top level and it's the same as globals().
It's safe in class definitions, right? At least in CPython it seems to work. I've done that a few times, most recently to dynamically generate enum members.
Hmm. I'm not actually sure there, but my belief is that it still isn't guaranteed - it just happens to work in current versions of CPython.
locals() Return a dictionary containing the current scope's local variables.
NOTE: Whether or not updates to this dictionary will affect name lookups in the local scope and vice-versa is *implementation dependent* and not covered by any backwards compatibility guarantees.
Correct, it's not guaranteed behaviour. "It seems to work" is as good as you'll get. PEP 558 (not yet accepted) proposes to standardise the behaviour. See the PEP for more detail. Paul
participants (4)
-
Alex Hall
-
Alexis Masson
-
Chris Angelico
-
Paul Moore