On 7/4/2018 9:35 AM, Steven D'Aprano wrote:
On Wed, Jul 04, 2018 at 05:02:07PM +1000, Chris Angelico wrote:
On Wed, Jul 4, 2018 at 4:07 PM, Serhiy Storchaka <storch...@gmail.com> wrote:
"Assignment is a statement" -- that's exactly the point under discussion.
I believe that this is Chris quoting and commenting on Serhiy having
said 'assigment is a statement'
Not any more it isn't. We've now gone from discussion to bitter
recriminations *wink*
I don't see any recrimination in what either said.
"del is a statement" -- yes, granted
"function and class declarations are statements" -- class, yes, but
you have "def" and "lambda" as statement and expression equivalents.
Even class can be re-written as a call to type(), if you need to. It's
probably not practical to do so in anything but the simplest cases, but
it is there.
Serhiy's viewpoint is a legitimate one. A major difference between def,
class, and import statements and equivalent lambda, type, and __import__
expressions is that the latter do not name-bind the resulting object.
This will continue to be true.
There is, however, precedent for subverting "assignment is a statement".
>>> class C():
pass
>>> c = C()
>>> c.a = 1
>>> setattr(c, 'b', 2)
>>> c.b
2
However, the target name, when given explicitly, is quoted. This
preserves the general rule that non-keyword identifiers in expressions
are immediately evaluated. The current exceptions are the 'and', 'or',
and 'if-else' constructs that embed flow control in expressions. But if
a name in such expressions is not ignored, it is evaluated normally.
The purpose of setattr is to allow the target attribute name to be any
variable or expression that evaluates to a string, so that one can do
the following.
>>> d = 'c'
>>> setattr(c, d+'2', 3)
>>> c.c2
3
or even
>>> setattr(c, input('aname: '), 33)
aname: qr
>>> c.qr
33
(An allowed side-effect is the possibility of adding attributes, such as
'2e', that can only be recovered with getattr.)
The same comments apply to globals().update({'foo':42}), pointed out by
David Merz in another post. (This specific form does not work does not
work within functions, as pointed out by Chris Angelico. But others do.)
A major difference between a while loop statement and an equivalent tail
recursion call (expression) is that while loops do explicit assignment
in the current namespace while recursive calls do implicit assignment in
a new (and unneeded) execution frame. The targets are the unquoted
parameter names in the function header. I regard the the easy use of
unevaluated unquoted names as a justification for having statements in
addition to expressions.
An alternate assignment-within-expressions proposal would be to follow
the setattr precedent. Add a builtin function 'set' with paramenters
'name' and 'value'. It would have to be built-in because Python code
cannot directly access function local namespaces. The problem, aside
from extra typing, is that efficient implementation of functions
requires that all local names be known at compile time. But a name
added by "set(input('name: '), <expr>)" is impossible to know.
Making the assignment target be an unquoted unevaluated non-keyword name
immediately followed by ':=' solves this. But it either introduces a
new and different type of exception to 'names in expressions are
evaluated', or one must regard 'assignment expression' as a new
statement-expression hybrid. Advocates of assignment expressions should
not really be surprised that this disquiets some people.
--
Terry Jan Reedy
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com