【问题标题】:Python 3 - Which one is faster for accessing data: dataclasses or dictionaries?Python 3 - 访问数据哪个更快:数据类或字典?
【发布时间】:2019-03-19 19:09:46
【问题描述】:

Python 3.7 引入了dataclasses 来存储数据。我正在考虑采用这种新方法,这种方法比字典更有条理,结构更合理。

但我有一个疑问。 Python 将键转换为 dicts 上的哈希,这使得查找键和值的速度更快。数据类实现类似的东西?

哪个更快,为什么?

【问题讨论】:

    标签: python dictionary python-3.7 python-dataclasses


    【解决方案1】:

    python 中的所有类实际上都在底层使用字典来存储它们的属性,您可以在文档中阅读here。有关 python 类(以及更多东西)如何工作的更深入参考,您还可以查看python's datamodel 上的文章,特别是关于自定义类的部分。

    因此,一般而言,从字典转移到数据类不会降低性能。但最好使用timeit 模块:


    基线

    # dictionary creation
    $ python -m timeit "{'var': 1}"
    5000000 loops, best of 5: 52.9 nsec per loop
    
    # dictionary key access
    $ python -m timeit -s "d = {'var': 1}" "d['var']"
    10000000 loops, best of 5: 20.3 nsec per loop
    

    基本数据类

    # dataclass creation
    $ python -m timeit -s "from dataclasses import dataclass" -s "@dataclass" -s "class A: var: int" "A(1)" 
    1000000 loops, best of 5: 288 nsec per loop
    
    # dataclass attribute access
    $ python -m timeit -s "from dataclasses import dataclass" -s "@dataclass" -s "class A: var: int" -s "a = A(1)" "a.var" 
    10000000 loops, best of 5: 25.3 nsec per loop
    

    在这里我们可以看到使用类确实有一些开销。对于类的创建,它的速度要慢一些(大约慢 5 倍),但只要您不打算每秒多次创建和折腾数据类,您就不必太在意它。

    属性访问可能是更重要的指标,虽然数据类再次变慢(~1.25 倍),但这次并没有那么慢。

    如果您认为这仍然有点太慢,您可以通过使用 slots 而不是字典来存储它们的属性来调整您的数据类(或任何类,真的):


    时隙数据类

    # dataclass creation
    $ python -m timeit -s "from dataclasses import dataclass" -s "@dataclass" -s "class A: __slots__ = ('var',); var: int" "A(1)" 
    1000000 loops, best of 5: 242 nsec per loop
    
    # dataclass attribute access
    $ python -m timeit -s "from dataclasses import dataclass" -s "@dataclass" -s "class A: __slots__ = ('var',); var: int" -s "a = A(1)" "a.var"
    10000000 loops, best of 5: 21.7 nsec per loop
    

    通过使用这种模式,我们可以再缩短几纳秒。在这一点上,至少在属性访问方面,字典应该不再有明显的差异,并且您可以在不影响速度的情况下使用数据类的优势。

    【讨论】:

    • 感谢您的回答!很简洁,很完整,解决了我所有的疑惑!
    • @SérgioMafra 很高兴我能帮上忙 =)
    • 尝试从字典列表中创建 10 000 个数据类。这确实需要很多时间,访问不是问题,问题是创建,很慢。
    • Python3.10 现在附带@dataclass(slots=True)!这模拟了所展示的开槽数据类的功能。使用python -m timeit -s "from dataclasses import dataclass" -s "@dataclass(slots=True)" -s "class A: var: int" "A(1)" 进行创建和python -m timeit -s "from dataclasses import dataclass" -s "@dataclass(slots=True)" -s "class A: var: int" -s "a = A(1)" "a.var" 进行访问,时间与我运行您的分槽数据类示例的时间相同。
    猜你喜欢
    • 2021-12-22
    • 2018-09-21
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 1970-01-01
    • 2016-12-20
    • 2014-05-12
    • 1970-01-01
    相关资源
    最近更新 更多