Steven D'Aprano
"> My favorite alternative is ?= if people think => and -> are getting
> overly loaded. What I really don't like is @param=[] because it puts the
> emphasis on the parameter name rather than the act of binding. Not only
> does it make it look like @param is a special kind of variable, it also
> mimics the *args and **kwargs syntax which makes them seem related.

But it *is* a special kind of parameter: it is a parameter that uses
late binding for the default value, instead of early binding.

Putting the emphasis on the parameter name is entirely appropriate.

Late bound parameters don't have a different sort of binding to other
parameters. There aren't two kinds of binding:"

Again: the important part is the *binding*, not the name of the parameter.
Right now, the order of reading something like `def load_tweets(... hash_tags: List[str] = None, ...)` goes like this:

1) there's a parameter named 'hash_tags'
2) it's a list of strings
3) it has a default value (bound at function declaration)
4) the default value is None

With `def load_tweets(... @hash_tags: List[str] = [], ...)` it goes like:

1) There's some parameter bound late
2) It's a parameter named 'hash_tags'
3) It's a list of strings
4) It has a default value (of course because of information we learned 3 steps ago)
5) The default value is an empty list

With `def load_tweets(... hash_tags: List[str] => [], ...)` it goes like:

1) there's a parameter named 'hash_tags'
2) it's a list of strings
3) it has a default value (bound at call-time)
4) the default value is None

Notice how it makes way more sense to put related parts closer together rather than saying "here's a little information. Now put a pin in that: we'll get back to it later on".

To drive the point home: The @ and = signs are connected, but not visually, which is confusing. You couldn't write @param without an '=' somewhere down the line:
`def load_tweets(... @hash_tags, ...)  # Error!`

I probably should have been more clear about what I meant when I said "it make[s] it look like @param is a special kind of variable, it also mimics the *args and **kwargs syntax which makes them seem related." Of course the way the parameter is bound *is* special making it, in the ways you pointed out, a "special kind of variable", however, again: the specialness is all about the binding of the variable, and: unlike *args and **kwargs, @param doesn't imply any specific type (in the 'type(kwargs)' sense) for the variable. We know that args and kwargs are an iterable and mapping, respectively.

The other question is: how important is the information that a parameter is late-binding. I've always been against the coding standard of making enums and constants ALL_CAPS because it makes code shouty and obnoxious just as it makes any other communication shouty and obnoxious. It doesn't seem like the fact that something is an enum or constant is important enough to warrant anything more than some syntax coloring from my IDE (if that). People always point out that the fact that something is an enum or constant is, in fact, information, and how else would they possibly communicate that information? The answer is: you communicate it by declaring an enum or constant and stop shouting at me! There's other information I you could put in your variable names that most sane people don't. You don't always append the name of the class of an object to the variable's name. You say 'hash_tags' not 'hash_tags_list_of_strings'.

In the same vein, I also don't see the need here to make a big fuss about the binding behavior of a parameter such that it *must* be up-front ahead of the name, annotation, and other binding info. It may seem like a big deal now because it's new and scary so we must prefix it with "HERE_BE_DRAGONS!!!", but years down the line when late-binding params are common place, it'll be a wart.
On Thursday, December 2, 2021 at 9:16:33 AM UTC-6 Steven D'Aprano wrote:
On Wed, Dec 01, 2021 at 09:58:11PM -0600, Abe Dillon wrote:

> My favorite alternative is ?= if people think => and -> are getting
> overly loaded. What I really don't like is @param=[] because it puts the
> emphasis on the parameter name rather than the act of binding. Not only
> does it make it look like @param is a special kind of variable, it also
> mimics the *args and **kwargs syntax which makes them seem related.

But it *is* a special kind of parameter: it is a parameter that uses
late binding for the default value, instead of early binding.

Putting the emphasis on the parameter name is entirely appropriate.

Late bound parameters don't have a different sort of binding to other
parameters. There aren't two kinds of binding:

1. Parameters with no default, and parameters with early bound default,
use the same old type of name binding that other local variables use
(local slots in CPython, maybe a dict for other implementations);

2. and parameters with late bound defaults use a different sort of name
binding, and we need a different syntax to reflect that.

That is wrong: there is only one sort of binding in Python (although it
can have a few different storage mechanisms: slots, cells and dict
namespaces, maybe even others). The storage mechanism is irrelevant.
It's all just name binding, and the implementation details are handled
by the interpreter.

By the time the function body is entered, all the parameters have been
bound to a value. (If there are parameters that don't have a value, the
interpreter raises an exception and you never enter the function body.)
It doesn't matter where those values came from, whether they were passed
in by the caller, or early bound defaults loaded from the cache, or late
bound defaults freshly evaluated. The value is bound to the parameter in
exactly the same way, and you cannot determine where that value came
from.


--
Steve
_______________________________________________
Python-ideas mailing list -- python...@python.org
To unsubscribe send an email to python-id...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python...@python.org/message/LYRLA3TH47H4EKOR3NCIUZKXJOICJ5R7/
Code of Conduct: http://python.org/psf/codeofconduct/