Evaluation of variable as f-string

Chris Angelico rosuav at gmail.com
Tue Jan 31 17:33:45 EST 2023


On Wed, 1 Feb 2023 at 09:14, Rob Cliffe via Python-list
<python-list at python.org> wrote:
> With great respect, Chris, isn't it for the OP (or anyone else) to
> decide - having been warned of the various drawbacks and limitations -
> to decide if it's a terrible idea *for him*?  He's entitled to decide
> that it's just what *he* needs, and that the drawbacks don't matter *for
> him".  Just as you're entitled to disagree.

It's an objectively bad idea. If the OP wants to do it, well, it's a
free world, but that doesn't mean I'm going to sugarcoat it and say
"oh yes, yes, you are totally right to do that".

> Thanks for clarifying.
> Hm.  So 'x' is neither in locals() nor in globals().  Which starts me
> wondering (to go off on a tangent): Should there be a nonlocals()
> dictionary?

I don't think so, but there might be some value in a dictionary
containing all available variables. It would have the same "don't
depend on writing" caveats that locals() has (or would be specifically
defined as a copy and thus disconnected), so its value would be
limited. And it would probably STILL be imperfect, because perfection
would require that it be a compiler construct, due to the way that
nonlocals are implemented.

>>> class Destructible:
...     def __init__(self, name): self.name = name
...     def __del__(self): print("Deleting", self.name)
...
>>> def func():
...     x = Destructible("x")
...     y = Destructible("y")
...     return lambda: x
...
>>> func()
Deleting y
<function func.<locals>.<lambda> at 0x7ff8c9897ce0>

The compiler is free to dispose of y as soon as func ends, but x has
to be retained for the inner function. So if there were any function
that could return every readable variable, it would have to force both
x and y to be retained; as such, it would have to be a compiler
construct. And given what happened with star imports in functions as
of Python 3, I am highly dubious that such a pessimisation would ever
be implemented.

> > Maybe you don't care. Maybe you do. But locals() is not the same as
> > "all names currently available in this scope". And, this example is
> > definitely not something I would recommend, but good luck making this
> > work with eval:
> >
> >>>> def func():
> > ...     x = 1
> > ...     print(f"{(x:=2)}")
> > ...     print(x)
> > ...
> >>>> func()
> > 2
> > 2
> > ...     x = 1
> > ...     print(eval("(x:=2)", globals(), locals()))
> > ...     print(x)
> > ...
> >>>> func()
> > 2
> > 1
> Now that, I have to admit, IS a challenge!

Exactly. This sort of thing is why the OP's idea as written is so bad:
it will cause many unnecessary corner cases, where the much simpler
idea of working it around format_map will actually behave sanely.

So I do not apologize for calling it a bad idea. It is a bad idea.
Lying about it won't change anything and won't help anyone.

ChrisA


More information about the Python-list mailing list