python的切片有多快

时间:2009-08-17 08:24:06

标签: python optimization

为了节省空间和必须保持不同源之间数据一致性的复杂性,我正在考虑存储某些子串的开始/结束索引,而不是存储子串本身。诀窍是,如果我这样做,我可能会一直创建切片。这是要避免的吗?切片操作员是否足够快我不需要担心?新对象创建/销毁开销怎么样?


好的,我吸取了教训。除非您尝试修复一个真正的问题,否则不要进行优化。 (当然这并不意味着对不必要的错误代码,但这不是重点......)另外,在堆栈溢出之前测试和配置文件。 = D谢谢大家!

5 个答案:

答案 0 :(得分:8)

  1. 足够快而不是什么?你现在怎么做?你究竟存储了什么,你究竟在检索什么?答案可能在很大程度上取决于此。这带给我们......

  2. 测量!不要在理论上进行讨论和分析;尝试并衡量什么是更高效的方式。然后确定可能的性能增益是否适合重构数据库。

  3. 编辑我刚刚运行了一个测试字符串切片与在(start, end)元组中键入的字典中查找的测试。它表明没有太大的区别。不过,这是一个非常天真的测试,所以请一点点盐。

答案 1 :(得分:3)

在评论中,OP提到了“在数据库中”的膨胀 - 但没有关于他正在谈论的数据库的信息;根据该评论中的缺乏信息,似乎Python字符串切片不一定是涉及的内容,而是“切片”将由数据库引擎在检索时完成。

如果这是实际情况,那么我会建议反对在DB中存储冗余信息的一般原则 - “正常形式”(可能在表达式的松散意义上;-),其中信息只存储一次并且派生信息重新计算(或数据库引擎的缓存费用等;-)应该是标准,并且通过故意存储派生信息的“非规范化”非常多的例外情况,并且只有在特定的,良好测量的检索性能需求得到证明的时候。

如果对“数据库”的引用是错误的方向;-),或者更确切地说,就像我在上面的“普通形式”所做的那样松散;-),那么另一个考虑可能适用:因为Python字符串是不可变的,所以通过复制不必进行切片似乎是很自然的,而是让每个切片重用它所切割的父级的内存空间的一部分(就像numpy数组的切片一样)。然而,这目前不是Python核心的一部分。我曾经尝试过一个针对这个目的的补丁,但是添加对大字符串的引用并因此使其留在内存中的问题仅仅是因为其中的一个微小的子串仍被大量引用以用于通用适应。仍然可以为大型“父”字符串需要保留在内存中的情况下创建字符串(和unicode之一)的特殊用途子类。目前buffer只做了一点,但你不能在缓冲区对象上调用字符串方法(没有先将它显式复制到字符串对象),所以它只对输出和一些特殊情况非常有用。 ..但是没有真正的概念性阻止添加字符串方法(我怀疑它将在核心中采用,但它应该很容易维护作为第三方模块无论如何; - )。

这种方法的价值很难通过测量以某种方式得到充分证明 - 速度与目前的隐式复制方法非常相似;优势完全在于减少内存占用,这不会使任何给定的Python代码更快,而是允许某个程序在RAM少一点的机器上执行,或者在多个实例中更好地执行多任务正在单独的过程中同时使用。有关在C ++环境中进行过实验的类似但更丰富的方法,请参阅rope(但请注意,它没有进入标准; - )。

答案 2 :(得分:1)

我也没有做过任何测量,但是因为听起来你已经采用C方法处理Python中的问题,你可能想看看Python's built-in mmap library

  

内存映射文件对象的行为类似于字符串和文件对象。然而,与普通的字符串对象不同,这些是可变的。您可以在大多数需要字符串的地方使用mmap对象;例如,您可以使用re模块搜索内存映射文件。由于它们是可变的,您可以通过执行obj [index] ='a'来更改单个字符,或者通过分配给切片来更改子字符串:obj [i1:i2] ='...'。您还可以从当前文件位置开始读取和写入数据,并通过文件搜索()到不同的位置。

我不确定你的问题是否正是你正在寻找的。值得重复的是,您需要进行一些测量。 Python's timeit library很容易使用,但也有cProfilehotshot,但{I} hotshot可能会被我从中理解后从标准库中删除。

答案 3 :(得分:1)

切片是否无效,因为它们会创建源字符串的副本?这可能是也可能不是问题。如果结果是一个问题,那么就不可能简单地实现“字符串视图”;一个对象,它具有对源字符串的引用并具有起点和终点。在访问/迭代时,它只是从源字符串中读取。

答案 4 :(得分:-1)

过早优化是所有邪恶的角色。

向自己证明你确实需要优化代码,然后采取行动。