gpt4 book ai didi

python - 通过普通类、数据类和命名元组创建对象的有趣性能

转载 作者:行者123 更新时间:2023-12-03 14:42:08 25 4
gpt4 key购买 nike

我正在浏览数据类并命名为元组。我发现这种行为在使用 python 的不同特性创建对象时具有不同的性能。
数据类

In [1]: from dataclasses import dataclass
...:
...: @dataclass
...: class Position:
...: lon: float = 0.0
...: lat: float = 0.0
...:

In [2]: %timeit for _ in range(1000): Position(12.5, 345)
326 µs ± 34.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
普通类:
In [1]: class Position:
...:
...: def __init__(self, lon=0.0, lat=0.0):
...: self.lon = lon
...: self.lat = lat
...:

In [2]: %timeit for _ in range(1000): Position(12.5, 345)
248 µs ± 2.89 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
命名元组:
In [2]: Position = namedtuple("Position", ["lon","lat"], defaults=[0.0,0.0])

In [3]: %timeit for _ in range(1000): Position(12.5, 345)
286 µs ± 13.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Python Env - Python 3.7.3  
OS - MacOS Mojave
所有实现都具有相同的对象属性、相同的默认值。
  • 为什么时间(data_classes) > time(named_tuple) > time(normal_class)是这个趋势?
  • 每个实现如何花费各自的时间?
  • 哪种实现在什么场景下表现最好?

  • 这里,时间表示创建对象所花费的时间。

    最佳答案

    here ,并提到 PEP-557。还有其他方法 - post_init .要验证,请使用 @dataclass(init=False) - 在这种情况下,不应调用该方法。
    更新
    看起来我最初的解释有点幼稚。 tl;博士:
    在 Python 中,一切都是字典。在数据类的情况下,该字典中有更多条目,因此反过来需要更多时间将它们放在那里。
    这种变化是怎么发生的? @Arne 的评论发现我在这里遗漏了一些东西。我做了示例代码:

    from dataclasses import dataclass
    import time

    @dataclass
    class Position:
    lon: float = 0.0
    lat: float = 0.0


    start_time = time.time()
    for i in range(100000):
    p = Position(lon=1.0, lat=1.0)
    elapsed = time.time() - start_time
    print(f"dataclass {elapsed}")
    print(dir(p))


    class Position2:
    lon: float = 0.0
    lat: float = 0.0

    def __init__(self, lon, lat):
    self.lon = lon
    self.lat = lat


    start_time = time.time()
    for i in range(100000):
    p = Position2(lon=1.0, lat=1.0)
    elapsed = time.time() - start_time
    print(f"just class {elapsed}")
    print(dir(p))

    start_time = time.time()
    for i in range(100000):
    p = {"lon": 1.0, "lat": 1.0}
    elapsed = time.time() - start_time
    print(f"dict {elapsed}")
    结果:
    /usr/bin/python3.8 ...../test.py
    dataclass 0.16358232498168945
    ['__annotations__', '__class__', '__dataclass_fields__', '__dataclass_params__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'lat', 'lon']
    just class 0.1495649814605713
    ['__annotations__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'lat', 'lon']
    dict 0.028212785720825195

    Process finished with exit code 0
    Dict例子供引用。
    看了 dataclass ,这个函数:
    (489) def _init_fn(fields, frozen, has_post_init, self_name, globals):
    负责创建构造函数。正如 Arne 发现的那样 - post_init 代码是可选的,不是生成的。我有其他想法,即有一些围绕领域的工作,但是:
    In [5]: p = Position(lat = 1.1, lon=2.2)                                                                                                                                                                           

    In [7]: p.lat.__class__
    Out[7]: float
    所以这里没有额外的包装/代码。从所有这些中我看到的唯一额外的东西 - 是更多的方法。

    关于python - 通过普通类、数据类和命名元组创建对象的有趣性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62912894/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com