
On Fri, Apr 28, 2017 at 09:54:55AM +1000, Chris Angelico wrote:
On Fri, Apr 28, 2017 at 9:21 AM, Steven D'Aprano <steve@pearwood.info> wrote:
What happens if you use this syntax in a top-level function rather than a method? (Or a static method?)
def function(x, y, x.attr): ...
(And don't forget that behind the scenes, methods *are* functions.) What would this syntax even mean?
Or if you use some other name other than the first parameter?
def method(self, spam, foo.eggs):
Exactly the same thing as:
def function(*args): x, y, x.attr = args
def method(*args): self, spam, foo.eggs = args
Obviously we can define syntax to do anything we like, but what is the logical connection between the syntax and the semantics? What part of "function parameter list" suggests "assign attributes to arbitrary objects"? Do we support arbitrary targets in their full generality? def function(arg, (name if name is not None else other).the_object.attr[0].method(foo)['key'].argument ): ... Of course, there are lots of things which are technically allowed but if someone is silly enough to do it, we say "don't do that". However, even the simple case is problematic: def trigonometry(x, y, math.pi) We could make that parameter declaration have the side-effect of assigning to math.pi, but that's a pretty surprising change to function declarations. Everything else declared inside a parameter list is local to the function: parameters themselves are local variables, default values and annotations are stored in the function not externally. The only thing which is not local is that default values may be arbitrary expressions, which may have side-effects, but that is not a declaration, its an expression evaluated for its value. What's the connection between parameter declarations and this sort of external side-effect? It seems pretty arbitrary to be a built-in part of the language, like having def function(x) automatically print x, or pickle it and upload the file to the cloud. (Obviously the side-effect doesn't occur until the function is called, but still, it is part of the parameter list declaration, not the body of the function.) I have grave doubts that people will find this obvious, let alone useful. Having a function declaration, the parameter list, have side-effects outside of the function seems like both a surprising and a bad idea to me.
It's well-defined - at least for positional args. Not sure what keyword arg handling would be though.
Why would it be any different? If it makes sense to allow: def function(spam, eggs, something.foo) assign to something.foo, then why should it matter whether it was called by keyword or positional? Or declared as keyword only? def function(spam, eggs, *, something.cheese) I don't think it makes sense either way, but it isn't because it is a keyword arg. I think it is arbitrarily mixing two distinct things into one convenient but confusing syntax. function(spam=1, eggs=2, something.cheese=3) # won't work -- Steve