在函数定义中使用双星语法,我们得到了一个正则字典。问题是它松散了用户输入顺序。有时,我们可能想知道关键字参数以何种顺序传递给函数。
由于通常函数调用不会涉及很多参数,所以我认为这不是性能问题,所以我想知道为什么默认不保持顺序。
我知道我们可以使用:
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/