python - 为什么 Python 的函数调用语义传入关键字参数没有顺序?

标签 python

在函数定义中使用双星语法,我们得到了一个正则字典。问题是它松散了用户输入顺序。有时,我们可能想知道关键字参数以何种顺序传递给函数。

由于通常函数调用不会涉及很多参数,所以我认为这不是性能问题,所以我想知道为什么默认不保持顺序。

我知道我们可以使用:

from collections import Ordereddict
def my_func(kwargs):
    print kwargs
my_func(Ordereddict(a=1, b=42))

但它不如以下简洁:

def my_func(**kwargs):
    print kwargs
my_func(a=1, b=42)

[编辑 1]:

1) 我认为有 2 种情况:

  • 我需要知道顺序,用户通过文档了解此行为。
  • 我不需要订单,所以我不在乎有没有订单。

我没想到即使用户知道它使用了命令,他也可以使用:

a = dict(a=1, b=42)
my_func(**a)

因为他不知道一个dict没有被命令(即使他应该知道)

2) 我认为在一些参数的情况下开销不会很大,因此拥有管理参数的新可能性的好处将优于这个缺点。

但是(从 Joe 的回答来看)开销似乎不可忽略。

[编辑 2]:

似乎PEP 0468 -- Preserving the order of **kwargs in a function正朝着这个方向发展。

最佳答案

因为字典没有按定义排序。我认为这真的很简单。 kwargs 的要点是准确处理那些未排序的形式参数。如果您确实知道顺序,那么您可以将它们作为“正常”参数或 *args 接收。

这是一个字典定义。

CPython implementation detail: Keys and values are listed in an arbitrary order which is non-random, varies across Python implementations, and depends on the dictionary’s history of insertions and deletions.

http://docs.python.org/2/library/stdtypes.html#dict

Python 的字典是整个语言工作方式的核心,因此它们经过了高度优化。添加排序会影响性能并需要更多的存储和处理开销。

您可能会遇到不正确的情况,但我认为这种情况比常见情况更为特殊。为非常热的代码路径添加“以防万一”功能不是明智的设计决策。

编辑:

仅供引用

>>> timeit.timeit(stmt="z = dict(x)", setup='x = ((("one", "two"), ("three", "four"), ("five", "six")))', number=1000000)
1.6569631099700928

>>> timeit.timeit(stmt="z = OrderedDict(x)", setup='from collections import OrderedDict; x = ((("one", "two"), ("three", "four"), ("five", "six")))', number=1000000)
31.618864059448242

在构建较小的“正常”大小字典时,速度大约有 30 倍的差异。 OrderedDict 是标准库的一部分,所以我不认为可以从中挤出更多的性能。

关于python - 为什么 Python 的函数调用语义传入关键字参数没有顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18077265/

相关文章:

python - 查找列表中最常见的元素

python - apt-get virtualenv 和 pip virtualenv 有什么区别?

python - 如何在变量中保存 tshark 统计数据

python - 可以在不提供默认值的情况下使用关键字参数吗?

python - 在文本中查找对称词

php - 对于 Django 中使用的小型且很少更改的数据,最快的缓存是什么?

python - Pandas :如何从相关矩阵中删除自相关

python - 使用 id() 函数比较 Python + IDLE 中的两个对象,结果不同

python - pyEphem - 计算非地球卫星的位置

python - 从 Conda 环境运行时,PyDev/Eclipse 不加载 _mklinit