[Python-ideas] Fwd: Define a method or function attribute outside of a class with the dot operator
Steven D'Aprano
steve at pearwood.info
Sun Feb 12 05:20:03 EST 2017
On Sun, Feb 12, 2017 at 03:50:03PM +1100, Chris Angelico wrote:
> >> def foo(x)[5](y, z):
> >> ...
[...]
> > Forget the parser. I know *I* can't cope with that.
> >
> > *wink*
>
> So you think the language should prevent silly assignments?
On a case-by-case basis, of course.
> >>> stuff = [None] * 10
> >>> def foo(): return stuff
> ...
> >>> for x, foo()[x] in enumerate(range(len(stuff))): pass
> ...
I have no idea what that does except by studying the code with great
care and essentially running it in my own mental Python interpreter.
Should it be prohibited? Not now, that would break backwards
compatibility.
If it were 1991 or thereabouts again, and Python 0.1 was newly released,
and somebody suggested an enhancement to the language that would
specifically allow that awfulness, would you be in favour of allowing
it? If it were 1991, I'd seriously consider arguing that the loop
assignment target should be restricted to a simple name or tuple of
names.
It's one thing to say "this abomination is allowed because of historical
reasons", and another to say "I think your proposal isn't general
enough. We should generalise your nice, clean, simple proposal to
something nobody in their right mind would ever use!"
In fact, if I were more cynical, I'd wonder whether you were trying to
sabotage this proposal by over-generalising it to something that has no
good use-cases. *multiple smileys*
There's a lot of this sort of thing on Python-Ideas:
"I think it would be good if Python included a stapler, as a
lightweight, quick and easy way to join sheets of paper."
"Excellent idea! I think the stapler should include a drill
attachment, a sledge hammer and a crowbar, in case you wish to
staple the paper to a concrete slab. You could use the drill with a
masonry bit to drill into the concrete slab, then you hammer the
extra-giant-size staple through the paper and the drill holes. Of
course you'll need to use the crowbar to flip the slab upside down
so you can hammer the other side of the staple flat. The slab might
be thicker than your drill bit, so the stapler also needs X-ray
imaging equipment so you can line up the holes you drill from each
side and ensure they meet up correctly."
*wink*
> Given that Python is happy to do these kinds of assignments in 'for'
> statements, I don't see any reason to prevent them in 'def'
> statements. It's not the language's job to prevent abuse; at best,
> that's a job for a style guide.
For many years, preventing this sort of abuse is exactly what the
language has done. This proposal is to introduce a *very slight*
loosening of the restriction, not tear the whole thing down.
There is plenty of good precedent for restricting assignment targets:
py> errors = [None]
py> try:
... pass
... except Exception as errors[0]:
File "<stdin>", line 3
except Exception as errors[0]:
^
SyntaxError: invalid syntax
py> import math as mymodules[-1]
File "<stdin>", line 1
import math as mymodules[-1]
^
SyntaxError: invalid syntax
And similar restrictions on decorators:
py> @decorators['key']
File "<stdin>", line 1
@decorators['key']
^
SyntaxError: invalid syntax
Its easy to loosen the restriction later if necessary, and all but
impossible to tighten it up again if the original decision turns out to
be a mistake. My view regarding syntax changes is, what is the
*smallest* change to syntax that will satisfy the use-case? Not the
broadest or most general.
It would be different if you had concrete use-cases for the
generalisation to any arbitrary assignment target. But as it stands, it
is a clear case of YAGNI, and it complicates the question of what
__name__ and __qualname__ should be set to.
--
Steve
More information about the Python-ideas
mailing list