On 3/2/2017 3:03 AM, Serhiy Storchaka wrote:
Function implemented in Python can have optional parameters with default
value. It also can accept arbitrary number of positional and keyword
arguments if use var-positional or var-keyword parameters (*args and
**kwargs).

In other words, Python signature possibilities are already unusually complex.

But there is no way to declare an optional parameter that
don't have default value.
... [moving the following up]
> I propose to add a new syntax for optional parameters. If the argument
> corresponding to the optional parameter without default value is not
> specified, the parameter takes no value.

-1

Being able to do this would violate what I believe is the fundamental precondition for python-coded function bodies: all parameters are bound to an object (so that using a parameter name is never a NameError); all arguments are used exactly once in the binding process; the binding is done without ambiguity (or resort to disambiguation rules). Calls that prevent establishment of this precondition result in an exception.

This precondition is normal in computing languages. I believe that all of the ~20 languages I have used over decades have had it. In any case, I believe it is important in understanding Python signatures and calls, and that there would need to be a strong reason to alter this precondition. (Stronger than I judge the one given here to be.)

> Currently you need to use the sentinel idiom

which binds a special object to a parameter, thus fulfilling the precondition.

for implementing this:

_sentinel = object()
def get(store, key, default=_sentinel):
    if store.exists(key):
        return store.retrieve(key)
    if default is _sentinel:
        raise LookupError
    else:
        return default

There are drawback of this:

* Module's namespace is polluted with sentinel's variables.

If one cares, one can change the internal reference to 'get._sentinel' and add
  get._sentinel = _sentinel; del _sentinel
after the def (or package this in a decorator.

* You need to check for the sentinel before passing it to other function
by accident.

This might be a feature.

* Possible name conflicts between sentinels for different functions of
the same module.

Since None can be used as a sentinel for multiple functions, I don't understand the problem you are pointing to.

* Since the sentinel is accessible outside of the function, it possible
to pass it to the function.

1. Give it a more private name (___private___?) similar to a reserved name.
2. Hide it better (as a object attribute, for instance).

* help() of the function shows reprs of default values. "foo(bar=<object
object at 0xb713c698>)" looks ugly.

Someone suggested a subclass of object with str = repr that prints something like 'bar = <undefined>'. I think functools would be the appropriate place for the class, predefined instance, and possibly a decorator. Make the instance an attribute of the class so it a) would have the same name both in the header and body, and b) would not be an attribute of user module or user functions.

__
Terry Jan Reedy


_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to