为什么Python的函数调用语义passin关键字参数没有排序?

2024-06-02 05:15:49 发布

您现在位置:Python中文网/ 问答频道 /正文

利用函数定义中的双星语法,得到了一个正则字典。问题是它失去了用户的输入顺序。有时,我们可能想知道关键字参数是按什么顺序传递给函数的。在

因为通常一个函数调用不涉及很多参数,所以我不认为这是性能问题,所以我想知道为什么默认情况下不维护顺序。在

我知道我们可以使用:

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

但它不如:

^{pr2}$

[编辑1]:

1)我认为有两种情况:

  • 我需要知道顺序,这个行为是用户通过文档知道的。在
  • 我不需要订单,所以我不在乎订单是否被订购。在

我没想到即使用户知道它在使用订单,他也可以使用:

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

因为他不知道口述是不有序的(即使他应该知道)

2)我认为在出现一些争论的情况下,开销不会太大,因此有一种新的可能来管理争论的好处将优于这种缺点。在

但从乔的回答来看,开销似乎不可忽视。在

[编辑2]:

似乎PEP 0468 -- Preserving the order of **kwargs in a function是朝这个方向走的。在


Tags: 函数用户订单编辑利用参数定义顺序
3条回答

作为反证,这里有一个例子说明这将导致复杂的语义。这里有几个案例:

  • 函数总是得到一个无序字典。在
  • 函数总是得到一个有序的字典-鉴于此,我们不知道顺序是否有任何意义,就像用户在一个无序的数据结构中传递一样,顺序将是任意的,而数据类型意味着顺序。在
  • 函数获取传入的任何内容-这看起来很理想,但并不是那么简单。在

关于some_func(a=1, b=2, **unordered_dict)的情况如何?原始关键字参数中存在隐式排序,但dict是无序的。在订购与否之间没有明确的选择。在

鉴于此,我认为对关键字参数进行排序是没有用的,因为无法判断顺序是否是任意的。这将模糊函数调用的语义。在

鉴于此,将此作为调用的一部分所获得的任何好处都将丢失—相反,只需将OrderedDict作为参数。在

因为字典不是按定义排序的。我觉得其实就是这么简单。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是标准库的一部分,所以我不认为它能提供更多的性能。在

如果函数的参数相互关联,以至于名称和顺序都很重要,请考虑使用特定的数据结构或定义一个类来保存它们。很可能,您希望它们在代码的其他地方一起使用,并可能定义使用它们的其他函数/方法。在

相关问题 更多 >