python - 请解释为什么这两个内置函数在传入关键字参数时表现不同

标签 python

考虑这些不同的行为::

>> 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

为什么 operator.sub 的行为与 int(x, [base]) 不同?

最佳答案

这是一个实现细节。 Python C API to retrieve arguments分隔位置参数和关键字参数。位置参数在内部甚至没有名称。

用于检索 operator.add 函数(以及类似的 sub)参数的代码是这样的:

PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)

如您所见,它不包含任何参数名称。与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)
#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.")

如您所见,唯一使用ab 的地方是在文档字符串中。方法定义也不使用方法接受关键字参数所必需的 METH_KEYWORDS 标志。

一般来说,您可以安全地假设一个您知道参数名称的基于 python 的函数将总是接受关键字参数(当然有人可以用 *args 解包但创建一个函数文档,其中参数看起来很正常),而 C 函数可能接受也可能不接受关键字参数。具有多个参数或可选参数的函数很有可能接受后面/可选参数的关键字参数。但是您几乎必须对其进行测试。

您可以在 python-ideas mailinglist 上找到有关支持关键字参数的讨论。 . Guido van Rossum(Benevolent Dictator For Life 又名 Python 的创造者)在其上也发表了声明:

Hm. I think for many (most?) 1-arg and selected 2-arg functions (and rarely 3+-arg functions) this would reduce readability, as the example of ord(char=x) showed.

I would actually like to see a syntactic feature to state that an argument cannot be given as a keyword argument (just as we already added syntax to state that it must be a keyword).

One area where I think adding keyword args is outright wrong: Methods of built-in types or ABCs and that are overridable. E.g. consider the pop() method on dict. Since the argument name is currently undocumented, if someone subclasses dict and overrides this method, or if they create another mutable mapping class that tries to emulate dict using duck typing, it doesn't matter what the argument name is -- all the callers (expecting a dict, a dict subclass, or a dict-like duck) will be using positional arguments in the call. But if we were to document the argument names for pop(), and users started to use these, then most dict sublcasses and ducks would suddenly be broken (except if by luck they happened to pick the same name).

关于python - 请解释为什么这两个内置函数在传入关键字参数时表现不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10894135/

相关文章:

python - Pandas 合并和求和数据帧

python - 计算多列中的值

python - 如何绘制正确的分布 TreeMap ?

python - 为什么我的 venv 使用的 pip 版本与我安装的不同

python - 安装Keras破坏了Conda虚拟环境(Windows 10)

python - float 总和 : unexpected result

python - 我无法在 torchrl 或其模块上使用导入。我从官方 github 存储库安装它 https ://github. com/pytorch/rl

python - 如何在QTest中的QGraphicsWidget上生成鼠标点击?

python - 针对可以在多个组织中担任角色的用户的模型设计

python - Pandas 。按索引分组并为列应用最大值