我正在做一些性能关键的Python工作,并希望创建一个函数,如果符合某些条件,则从列表中删除一些元素.我宁愿不创建列表的任何副本,因为它充满了很多非常大的对象.
我想实现的功能:
def listCleanup(listOfElements):
i = 0
for element in listOfElements:
if(element.meetsCriteria()):
del(listOfElements[i])
i += 1
return listOfElements
myList = range(10000)
myList = listCleanup(listOfElements)
Run Code Online (Sandbox Code Playgroud)
我不熟悉Python的低级工作方式.myList是通过值还是通过引用传递的?
我怎样才能让它更快?
有可能以某种方式扩展列表类并在其中实现listCleanup()吗?
myList = range(10000)
myList.listCleanup()
Run Code Online (Sandbox Code Playgroud)
谢谢-
乔纳森
Mik*_*ham 29
Python以相同的方式传递所有内容,但是"按值"或"按引用"调用它不会清除所有内容,因为Python的语义与这些术语通常适用的语言不同.如果我要描述它,我会说所有传递都是按值,并且该值是对象引用.(这就是我不想说的原因!)
如果要从列表中过滤掉一些内容,可以构建一个新列表
foo = range(100000)
new_foo = []
for item in foo:
if item % 3 != 0: # Things divisble by 3 don't get through
new_foo.append(item)
Run Code Online (Sandbox Code Playgroud)
或者,使用列表推导语法
new_foo = [item for item in foo if item % 3 != 0]
Run Code Online (Sandbox Code Playgroud)
Python将不会复制的对象列表,而是两者foo
并new_foo
会引用同一个对象.(Python从不隐式复制任何对象.)
您已建议您对此操作有性能问题.使用del
旧列表中的重复 语句将导致代码不再具有惯用性并且更难以处理,但它将引入二次性能,因为每次必须重新整理整个列表.
解决性能问题:
启动并运行.除非你有代码工作,否则你无法弄清楚你的表现是什么样的.这也将告诉您是否必须优化速度或空间; 你在代码中提到了对这两者的关注,但通常优化涉及以另一个为代价获得一个.
轮廓.您可以使用stdlib工具及时获得性能.有各种第三方内存分析器可能有点用,但不太适合使用.
测量. 当您进行更改以查看更改是否有所改进时,时间或重新编码内存,如果是,那么改进是什么.
为了使您的代码对内存更敏感,您通常需要在存储数据的方式上进行范式转换,而不是像不构建第二个列表来进行过滤的微观优化.(对于时间也是如此,真的:改为更好的算法几乎总能提供最佳的加速.然而,更难以概括速度优化).
在Python中优化内存消耗的一些常见范例转换包括
使用生成器.生成器是懒惰的迭代:它们不会立即将整个列表加载到内存中,它们会在运行中找出它们的下一个项目.要使用生成器,上面的代码段看起来像
foo = xrange(100000) # Like generators, xrange is lazy
def filter_divisible_by_three(iterable):
for item in foo:
if item % 3 != 0:
yield item
new_foo = filter_divisible_by_three(foo)
Run Code Online (Sandbox Code Playgroud)
或者,使用生成器表达式语法,
new_foo = (item for item in foo if item % 3 != 0)
Run Code Online (Sandbox Code Playgroud)使用numpy
为均质的序列,特别是那些是数值-mathy.这也可以加速执行大量矢量操作的代码.
将数据存储到磁盘,例如数据库中.
在Python中,列表总是通过引用传递.
列表中对象的大小不会影响列表性能,因为列表仅存储对对象的引用.但是,列表中的项目数确实会影响某些操作的性能 - 例如删除元素,即O(n).
正如所写的那样,listCleanup是最坏情况的O(n**2),因为你在一个可能是O(n)本身的循环中有O(n)del操作.
如果元素的顺序无关紧要,您可以使用内置set
类型而不是列表.所述set
具有O(1)缺失和插入.但是,您必须确保对象是不可变和可清除的.
否则,你最好重新创建列表.那是O(n),你的算法需要至少为O(n),因为你需要检查每个元素.您可以在一行中过滤列表,如下所示:
listOfElements[:] = [el for el in listOfElements if el.MeetsCriteria()]
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
16967 次 |
最近记录: |