[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 

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 

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."


> 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
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.


More information about the Python-ideas mailing list