在内存使用和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中,它将工作并显示项目列表。问题是它显示了所有项目的所有列表。我只希望单击项目的列表可见: 如果我在之后添加括号,我会收到以下警告: 警告:在现有状态转换期间(例如在
问题内容: 什么的Unicode 字符编码 一个确实对象对应于: C# 爪哇 JavaScript (我知道实际上没有类型,但是我假设该类型仍然实现为Unicode字符数组) 通常,在编程语言之间是否存在使用特定 字符编码 的通用约定 ? 更新资料 我试图澄清我的问题。我所做的更改将在下面的评论中讨论。 回复:“您要解决什么问题?” ,我对从独立于语言的表达式生成代码感兴趣,并且文件的特定编码是相