当前位置: 首页 > 面试题库 >

字典与对象-哪个更有效,为什么?

堵存
2023-03-14
问题内容

在内存使用和CPU消耗方面,在Python中更有效的方法是-字典还是对象?

背景:
我必须将大量数据加载到Python中。我创建了一个只是字段容器的对象。创建4M实例并将其放入字典中大约需要10分钟和6GB的内存。字典准备就绪后,只需眨眼即可访问。

示例: 为了检查性能,我编写了两个简单的程序,它们执行相同的操作-一个使用对象,另一个使用字典:

对象(执行时间〜18sec):

class Obj(object):
  def __init__(self, i):
    self.i = i
    self.l = []
all = {}
for i in range(1000000):
  all[i] = Obj(i)

字典(执行时间约12秒):

all = {}
for i in range(1000000):
  o = {}
  o['i'] = i
  o['l'] = []
  all[i] = o

问题: 我做错什么了吗?还是字典比对象快?如果确实词典性能更好,有人可以解释为什么吗?


问题答案:

您是否尝试过使用__slots__

从文档中:

默认情况下,新旧类的实例都具有用于存储属性的字典。这浪费了具有很少实例变量的对象的空间。创建大量实例时,空间消耗会变得非常大。

可以通过__slots__在新式类定义中进行定义来覆盖默认值。该__slots__声明采用一系列实例变量,并在每个实例中仅保留足够的空间来容纳每个变量的值。因为__dict__未为每个实例创建空间,所以节省了空间。

那么,这样既节省时间又节省内存吗?

比较计算机上的三种方法:

test_slots.py:

class Obj(object):
  __slots__ = ('i', 'l')
  def __init__(self, i):
    self.i = i
    self.l = []
all = {}
for i in range(1000000):
  all[i] = Obj(i)

test_obj.py:

class Obj(object):
  def __init__(self, i):
    self.i = i
    self.l = []
all = {}
for i in range(1000000):
  all[i] = Obj(i)

test_dict.py:

all = {}
for i in range(1000000):
  o = {}
  o['i'] = i
  o['l'] = []
  all[i] = o

test_namedtuple.py(在2.6中受支持):

import collections

Obj = collections.namedtuple('Obj', 'i l')

all = {}
for i in range(1000000):
  all[i] = Obj(i, [])

运行基准测试(使用CPython 2.5):

$ lshw | grep product | head -n 1
          product: Intel(R) Pentium(R) M processor 1.60GHz
$ python --version
Python 2.5
$ time python test_obj.py && time python test_dict.py && time python test_slots.py

real    0m27.398s (using 'normal' object)
real    0m16.747s (using __dict__)
real    0m11.777s (using __slots__)

使用CPython 2.6.2,包括命名的元组测试:

$ python --version
Python 2.6.2
$ time python test_obj.py && time python test_dict.py && time python test_slots.py && time python test_namedtuple.py

real    0m27.197s (using 'normal' object)
real    0m17.657s (using __dict__)
real    0m12.249s (using __slots__)
real    0m12.262s (using namedtuple)

因此,是的(不是很意外),使用__slots__是一种性能优化。使用命名元组的性能与相似__slots__



 类似资料:
  • 问题内容: 我有一个嵌套的字典,我们称它为字典d。该词典的键是一个整数,每个键的值是另一个词典。我正在python 2.7上尝试一个简单的代码来更新一个外键的值,但似乎它正在更新外键的ALL的值。 希望这些代码将使其更易于理解。这是我的意见。 然后是输出: 您会看到,我只为d [0] [‘mean’]分配了‘1’,但是d [1] [‘mean’]也有所更新。如果我增加d键的数量,它将只更改所有d键

  • 问题内容: 什么更快: (A)使用以下方法“取消腌制”(加载)腌制的字典对象 要么 (B)使用以下命令将JSON文件加载到字典中 假定:案例A中已经存在腌制的对象文件,案例B中已经存在JSON文件。 问题答案: 速度实际上取决于数据,内容和大小。 但是,无论如何,让我们以json数据为例,看看什么更快(Ubuntu 12.04,python 2.7.3): pickle cPickle json

  • 7.2 字典即对象 字典是 VimL 中最复杂全能的数据结构,基于字典,几乎就能实现面向对象风格的编程。 在本章中,我们提到 VimL 中的一个对象时,其实就是指一个字典结构变量。 按对象属性方式访问字典键 首先要了解的是一个语法糖。一般来说,访问字典某一元素的索引方法与列表是类似的, 用中括号 [] 表示。只不过列表是用整数索引,字典是用字符串(称为字典的键)索引 。例如: : echo aLi

  • 问题内容: String s = “”; for(i=0;i<....){ s = some Assignment; } 要么 我不需要在循环外再次使用“ s”。第一个选项可能更好,因为不会每次都初始化一个新的String。但是,第二个结果将导致变量的范围仅限于循环本身。 编辑:回应米尔豪斯的回答。在循环中将String分配给常量是没有意义的吗?不,这里的“某些分配”是指从要迭代的列表中获得的变化

  • 使用React,我有一个包含信息的div,其中另一个div包含项目列表。我希望第二个div(列表)可以在单击时折叠。如果我将click listener放在第一个div中,它将工作并显示项目列表。问题是它显示了所有项目的所有列表。我只希望单击项目的列表可见: 如果我在之后添加括号,我会收到以下警告: 警告:在现有状态转换期间(例如在

  • 问题内容: 当使用范围表达式迭代大数组时,我应该使用Python的内置范围函数还是numpy来获得最佳性能? 到目前为止,我的推理是: 可能求助于本机实现,因此可能会更快。另一方面,返回一个占用内存的完整数组,因此可能会产生开销。Python 3的范围表达式是一个生成器,它不会在内存中保存所有值。 问题答案: 对于大型数组,numpy应该是更快的解决方案。 在numpy中,您应该结合使用向量化计算