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/