[Python-ideas] Tighten up the formal grammar and parsing a bit?
Steven D'Aprano
steve at pearwood.info
Mon May 15 08:29:33 EDT 2017
On Mon, May 15, 2017 at 07:38:29PM +1000, Hugh Fisher wrote:
> I wrote this little Python program using CPython 3.5.2. It's ...
> interesting ... that we apparently don't need comments or pass
> statements any more.
I'm not sure what you mean by "any more". The code you give works,
unchanged, all the way back to Python 2.0 when augmented assignment was
added. If you replace the
x += 1
with
x = x + 1
it works all the way back to Python 1.5 and probably even older. Python
has (more or less) always supported arbitrary expressions as statements,
so this is not new. This is a feature, not a bug: supporting expressions
as statements is necessary for expressions like:
alist.sort()
and other expressions with side-effects. Unfortunately, that means that
pointless expressions like:
42
that have no purpose are also legal.
In recent versions, the compiler has a peephole optimizer that removes
at least some constant expressions:
# Python 3.5
py> block = """x = 1
... 'some string'
... 100
... y = 2
... """
py> code = compile(block, '', 'exec')
py> from dis import dis
py> dis(code)
1 0 LOAD_CONST 0 (1)
3 STORE_NAME 0 (x)
4 6 LOAD_CONST 1 (2)
9 STORE_NAME 1 (y)
12 LOAD_CONST 2 (None)
15 RETURN_VALUE
There's also a (weak) convention that bare string literals are intended
as pseudo-constants. That's especially handy with triple-quoted strings,
since they can comment-out multiple lines.
> Anyone else think it might be worth tightening up
> the grammar definition and parser a bit?
Not me.
In fact, I'd go further than just saying "I don't think it is
worthwhile". I'll say that treating bare strings as pseudo-comments is
a positive feature worth keeping. Tightening up the grammar to prohibit
that is a bad thing.
There's an argument to be made that bare expressions like:
100
are pointless, but it isn't a strong argument. In practice, it isn't
really a common source of errors, and as far as efficiency goes, the
peephole optimizer solves that.
And its easy to get the rules wrong. For instance, at first I thought
that a bare name lookup like:
x
could be safely optimized away, or prohibited, but it can't. It is true
that a successful name lookup will do nothing, but not all lookups are
successful:
try:
next
except NameError:
# Python version is too old
def next(iterator):
return iterator.next()
If we prohibit bare name lookups, that will break a lot of working code.
I suppose it is possible that a *sufficiently intelligent* compiler
could recognise bare expressions that have no side-effects, and prohibit
them, and that this might prevent some rare, occasional errors:
x #= 1 # oops I meant +=
but honestly, I don't see that this is a good use of developer's time.
It adds complexity to the language, risks false positives, and in my
opinion is the sort of thing that is better flagged by a linter, not
prohibited by the interpreter.
--
Steve
More information about the Python-ideas
mailing list