Well, I think these are mostly artifacts from old times, and usually passing None *should* be the same as omitting the argument. But check each case!
On Wednesday, January 15, 2014, Larry Hastings <la...@hastings.org> wrote: > > On 01/15/2014 08:35 PM, Ryan Smith-Roberts wrote: > > On Wed, Jan 15, 2014 at 7:57 PM, Ryan Smith-Roberts > <r...@lab.net<javascript:_e({}, 'cvml', 'r...@lab.net');> > > wrote: > >> socket.getservbyname(servicename[, protocolname]) >> -> >> socket.getservbyname(servicename, protocolname=None) >> > > Here is a more complicated example, since the above does technically > have an alternative fix: > > sockobj.sendmsg(buffers[, ancdata[, flags[, address]]]) > -> > sockobj.sendmsg(buffers, ancdata=None, flags=0, address=None) > > > I feel like Ryan didn't sufficiently explain the problem. I'll elaborate. > > > For functions implemented in Python, it's always true that: > > - a parameter that is optional always has a default value, and > - this default value is visible to Python and is a Python value. > > The default value of every parameter is part of the function's > signature--you can see them with inspect.signature() or > inspect.getfullargspec(). > > A corollary of this: for every function implemented in Python, you can > construct a call to it where you fill in every optional value with its > published default value, and this is exactly equivalent to calling it > without specifying those arguments: > > def foo(a=any_python_value): ... > > sig = inspect.signature(foo) > defaults = [p.default for p in sig.parameters.values()] > foo(*defaults) == foo() > > Assuming neither foo nor "any_python_value" have side effects, those two > calls to foo() will be exactly the same in every way. > > > But! Builtin functions implemented in C commonly have optional parameters > whose default value is not only opaque to Python, it's not renderable as a > Python value. That default value is NULL. Consider the first two > paragraphs of SHA1_new() in Modules/sha1module.c: > > static PyObject * > SHA1_new(PyObject *self, PyObject *args, PyObject *kwdict) > { > static char *kwlist[] = {"string", NULL}; > SHA1object *new; > PyObject *data_obj = NULL; > Py_buffer buf; > > if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|O:new", kwlist, > &data_obj)) { > return NULL; > } > ... > > The "string" parameter is optional. Its value, if specified, is written > to "data_obj". "data_obj" has a default value of NULL. There is no Python > value you could pass in to this function that would result in "data_obj" > being (redundantly) set to NULL. In Python SHA1_new is known as > "_sha1.sha1". And: > > sig = inspect.signature(_sha1.sha1) > defaults = [p.default for p in sig.parameters.values()] > _sha1.sha1(*defaults) == _sha1.sha1() > > There's no value we could put in the signature for _sha1.sha1 that would > behave exactly the same as that NULL. > > The ultimate goal of Argument Clinic is to provide introspection > information for builtins. But we can't provide a default value to Python > for the "string" parameter to _sha1.sha1() without changing the semantics > of the function. We're stuck. > > Ryan's question, then, is "can we change a function like this so it > accepts None?" My initial reaction is "no". That might be okay for > _sha1.sha1(), but it'd be best to avoid. > > In the specific case of SHA1_new's "string" parameter, we could lie and > claim that the default value is b''. Internally we could still use NULL as > a default and get away with it. But this is only a happy coincidence. > Many (most?) functions like this won't have a clever Python value we can > trick you with. > > What else could we do? We could add a special value, let's call it > sys.NULL, whose specific semantics are "turns into NULL when passed into > builtins". This would solve the problem but it's really, really awful. > > The only other option I can see: don't convert SHA1_new() to use Argument > Clinic, and don't provide introspection information for it either. > > Can you, gentle reader, suggest a better option? > > > */arry* > > p.s. Ryan's function signatures above suggest that he's converting code > from using PyArg_ParseTuple into using PyArg_ParseTupleAndKeywords. I > don't think he's *actually* doing that, and if I saw that in patches > submitted to me I would ask that it be fixed. > -- --Guido van Rossum (on iPad)
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com