考虑这些不同的行为::
>> def minus(a, b):
>> return a - b
>> minus(**dict(b=2, a=1))
-1
>> int(**dict(base=2, x='100'))
4
>> import operator
>> operator.sub.__doc__
'sub(a, b) -- Same as a - b.'
>> operator.sub(**dict(b=2, a=1))
TypeError: sub() takes no keyword arguments
Run Code Online (Sandbox Code Playgroud)
为什么operator.sub表现与众不同int(x, [base])?
这是一个实现细节.用于检索参数的Python C API将位置和关键字参数分开.位置参数内部甚至没有名称.
用于检索operator.add函数的参数(以及类似的函数sub)的代码是:
PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)
Run Code Online (Sandbox Code Playgroud)
如您所见,它不包含任何参数名称.与之相关的整个代码operator.add是:
#define spam2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
PyObject *a1, *a2; \
if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
return AOP(a1,a2); }
spam2(op_add , PyNumber_Add)
Run Code Online (Sandbox Code Playgroud)
#define spam2(OP,ALTOP,DOC) {#OP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)}, \
{#ALTOP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)},
spam2(add,__add__, "add(a, b) -- Same as a + b.")
Run Code Online (Sandbox Code Playgroud)
如您所见,唯一使用a和b使用的位置是docstring.方法定义也不使用METH_KEYWORDS该方法接受关键字参数所必需的标志.
一般来说,你可以放心地假设一个基于python的函数,你知道一个参数名称将始终接受关键字参数(当然有人可以通过*args解包但创建一个函数doc,其中参数看起来正常),而C函数可以或可能不接受关键字参数.有多个参数或可选参数的函数接受后来/可选参数的关键字参数,这是很好的.但你几乎要测试它.
你可以在python-ideas邮件列表的各个地方找到关于支持关键字参数的讨论.还有一个来自Guido van Rossum(仁慈的Dictator For Life,也就是Python的创造者)的声明:
嗯.我认为对于许多(大多数?)1-arg和选择的2-arg函数(以及很少3 + -arg函数),这会降低可读性,如ord(char = x)所示.
我真的希望看到一个语法特性,声明一个参数不能作为关键字参数给出(就像我们已经添加语法来声明它必须是一个关键字).
我认为添加关键字args的一个方面是完全错误的:内置类型或ABC的方法是可覆盖的.例如,考虑dict上的pop()方法.由于参数名称当前未记录,如果有人子类dict并覆盖此方法,或者如果他们创建另一个可变映射类,尝试使用duck typing来模拟dict,则参数名称是什么并不重要 - 所有调用者(期待dict,dict子类或dict-like duck)将在调用中使用位置参数.但是如果我们要记录pop()的参数名称,并且用户开始使用这些,那么大多数dict sublcasses和ducks会突然被破坏(除非幸运的是他们碰巧选择了相同的名字).
| 归档时间: |
|
| 查看次数: |
719 次 |
| 最近记录: |