字典在Python 3.6中排序(至少在CPython实现下),与之前的版本不同.这似乎是一个重大变化,但它只是文档中的一小段.它被描述为CPython实现细节而不是语言特性,但也暗示这可能成为未来的标准.
在保留元素顺序的同时,新字典实现如何比旧字典实现更好?
以下是文档中的文字:
dict()现在使用PyPy开创的"紧凑"表示.与Python 3.5相比,新dict()的内存使用量减少了20%到25%.PEP 468(在函数中保留**kwargs的顺序.)由此实现.这个新实现的顺序保留方面被认为是一个实现细节,不应该依赖(这可能会在未来发生变化,但是在更改语言规范之前,希望在几种版本的语言中使用这个新的dict实现为所有当前和未来的Python实现强制命令保留语义;这也有助于保持与随机迭代顺序仍然有效的语言的旧版本的向后兼容性,例如Python 3.5).(由INADA Naoki在issue 27350中提供.最初由Raymond Hettinger提出的想法.)
2017年12月更新:Python 3.7 保证了dict保留插入顺序
阅读如何super()工作,我遇到了关于如何创建有序计数器的这个方法:
from collections import Counter, OrderedDict
class OrderedCounter(Counter, OrderedDict):
'Counter that remembers the order elements are first seen'
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__,
OrderedDict(self))
def __reduce__(self):
return self.__class__, (OrderedDict(self),)
Run Code Online (Sandbox Code Playgroud)
例如:
oc = OrderedCounter('adddddbracadabra')
print(oc)
OrderedCounter(OrderedDict([('a', 5), ('d', 6), ('b', 2), ('r', 2), ('c', 1)]))
Run Code Online (Sandbox Code Playgroud)
有人能够解释这是如何神奇地起作用的吗?
这也出现在Python文档中.
我们知道在Python 3.6中,字典是作为实现细节排序的插入,并且可以依赖3.7插入顺序.
我希望这也适用于dict诸如collections.Counter和的子类collections.defaultdict.但这似乎只适用于defaultdict此案.
所以我的问题是:
defaultdict但不适用于Counter?如果是这样,是否有直接的解释?dict将collections模块中这些子类的顺序视为实现细节?或者,例如,我们可以依赖于defaultdict像dictPython 3.7+ 那样的插入顺序吗?以下是我的基本测试:
dict:有序
words = ["oranges", "apples", "apples", "bananas", "kiwis", "kiwis", "apples"]
dict_counter = {}
for w in words:
dict_counter[w] = dict_counter.get(w, 0)+1
print(dict_counter)
# {'oranges': 1, 'apples': 3, 'bananas': 1, 'kiwis': 2}
Run Code Online (Sandbox Code Playgroud)
反:无序
from collections import Counter, defaultdict
print(Counter(words))
# Counter({'apples': 3, 'kiwis': 2, 'oranges': 1, 'bananas': 1})
Run Code Online (Sandbox Code Playgroud)
defaultdict:ordered
dict_dd …Run Code Online (Sandbox Code Playgroud) 我有一个日期列表,目标是计算每个日期的出现次数,同时保持它们在原始列表中的显示顺序.请考虑以下示例:
该列表only_dates如下所示:
[datetime.date(2017, 3, 9), datetime.date(2017, 3, 10), datetime.date(2017, 3, 10), datetime.date(2017, 3, 11)]
Run Code Online (Sandbox Code Playgroud)
我正在尝试使用groupby:
import itertools
day_wise_counts = [(k, len(list(g))) for k, g in itertools.groupby(only_dates)]
print(str(day_wise_counts))
Run Code Online (Sandbox Code Playgroud)
这打印
[(datetime.date(2017, 3, 10), 1), (datetime.date(2017, 3, 9), 1), (datetime.date(2017, 3, 10), 1), (datetime.date(2017, 3, 11), 1)]
Run Code Online (Sandbox Code Playgroud)
我理解这种情况正在发生,因为最终每个日期对象在分组时被视为不同的日期对象.
我期待输出为:
[(datetime.date(2017, 3, 9), 1), (datetime.date(2017, 3, 10), 2), (datetime.date(2017, 3, 11), 1)]
Run Code Online (Sandbox Code Playgroud)
我不一定在寻找元组列表.只要保持原始日期顺序,字典输出也就足够了.(OrderedDict也许).
我怎样才能做到这一点?
更新:有可能建议多种方法都能正常运行.但我应该提到我将为大量数据执行此操作.因此,如果您的解决方案在运行时间方面是最佳的,那就太好了.如果可以,请相应地编辑您的答案/评论.
更新2:数据大小可以达到100万行.
python ×4
python-3.x ×4
dictionary ×3
counter ×2
counting ×1
datetime ×1
defaultdict ×1
list ×1
python-3.6 ×1