belows is in builtins.pyi
def max(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], SupportsLessThan]) -> _T:
I do know what the name mangling means and know that the name mangling will influence every "__xxx" identifier as long as in class definition field.
So I have three questions:
Many thanks.
further work:
def wat1(__a):
def wat2(__b):
return __b, __a
return __a
print(wat1.__code__.co_varnames)
print(wat1.__code__.co_cellvars)
dis.dis(wat1)
output(linux python==3.10.8):
('__a', 'wat2')
('__a',)
21 0 LOAD_FAST 0 (__a)
2 RETURN_VALUE
22 0 LOAD_FAST 0 (__b)
2 LOAD_DEREF 0 (__a)
4 BUILD_TUPLE 2
6 RETURN_VALUE
Name mangling applies only to names used in a class definition, not function parameters. In this case the leading underscores are only a naming convention to indicate that parameters with such names are not to be passed with keyword arguments, but rather only positional ones.
This is to say that you should call max with:
max(1, 2)
rather than:
max(__arg1=1, __arg2=2)
The key argument on the other hand, are named without an underscore prefix, indicating that it is meant to be passed with a keyword argument:
max(1, -2, key=abs)
Thanks for @blhsing's answer and @zvone's comment, to summarize the above, I' d like to share my understand of it.
Here is cpython source code part of max() :
static PyObject *
min_max(PyObject *args, PyObject *kwds, int op)
{
PyObject *v;
static char *kwlist[] = {"key", "default", NULL};
const int positional = PyTuple_Size(args) > 1;
int ret;
if (positional) {
v = args;
}
else if (!PyArg_UnpackTuple(args, name, 1, 1, &v)) {
if (PyExceptionClass_Check(PyExc_TypeError)) {
PyErr_Format(PyExc_TypeError, "%s expected at least 1 argument, got 0", name);
}
return NULL;
}
If using keyword argument to pass args to max(), arguments here will drop in PyObject* kwds rather than PyObject* args so PyArg_UnpackTuple will get nothing and return false, then raise a TypeError in python level as expected.
So it's a powerful purpose to use positional one here?
Also it's just a convention now with no constraint but new positional only arguments syntax do restrict. So belows is possible.
def wat1(__a):
return __a
wat1(__a=1)
New one would be preferred instead of the old naming convention because it make input arguments more contrllable.
For some reason builtin.pyi don't apply this new positional syntax, maybe historical issues? I cannot figure it out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With