【问题标题】:Avoiding loops in python when using classes使用类时避免python中的循环
【发布时间】:2015-11-21 19:49:48
【问题描述】:

我正在使用我在使用 for 循环填充时使用的 python 类,当我循环数百万条数据线时它非常慢,显然有一种更快的方法。也许我根本不应该使用一个类,但我需要创建一个结构以便对它进行排序。

这是那个类:

class Particle(object):
def __init__(self, ID, nH, T, metallicity,oxygen,o6,o7,o8):
    self.ID = ID
    self.nH = nH
    self.T = T
    self.metallicity = metallicity
    self.oxygen = oxygen
    self.o6 = o6
    self.o7 = o7
    self.o8 = o8

这是我在使用 append 读取所有单个数组(ID、nH、T 等)后第一次填充它的方法,这当然非常慢:

partlist = []

for i in range(npart):
     partlist.append(Particle(int(ID[i]),nH[i],T[i],metallicity[i],oxygen[i],o6[i],o7[i],o8[i]))

这需要几个小时才能处理 3000 万个值,显然“追加”不是正确的做法。我认为这是一种改进:

partlist = [Particle(int(ID[i]),nH[i],T[i],metallicity[i],oxygen[i],o6[i],o7[i],o8[i]) for i in range(npart)]

但这可能需要同样长的时间,并且在一个小时后还没有完成。

我是 python 新手,使用索引不是“pythonic”,但我不知道如何在几分钟内制作和填充 python 对象。

建议?提前致谢。

【问题讨论】:

  • 您需要先了解range()xrange() 之间的区别,因为3000 万件就是3000 万件。
  • 你也可以避免在生成器之前使用lists。
  • 而列表理解只是您已经在做的事情的语法糖。
  • 您真的需要列表中的所有Particle 对象,还是一次只使用一个?如果您一次只需要一个值,那么像 zip(在 Python 3 中或在 Python 2 中为 itertools.izip)这样的生成器可能会更好。
  • 列表推导不是语法糖。循环必须反复调用函数partlist.append;列表推导使用LIST_APPEND 字节码添加到正在构建的列表中。

标签: python class object for-loop indexing


【解决方案1】:

为工作使用正确的工具:

您首先需要研究更有效的数据结构。 如果您需要一次将整个数据集存储在内存中,那么常规对象将不是您尝试做的最佳解决方案。

use xrange() instead of range()

range(30000000) 在内存中创建一个包含 30,000,000 个数字的列表,xrange() 不像生成器那样计算。

.

使用numpy 高效地存储和处理数组中的数据。

除了其明显的科学用途外,NumPy 还可以用作 通用数据的高效多维容器。随意的 可以定义数据类型。这允许 NumPy 无缝地 快速与各种数据库集成。

处理:

研究stream 处理和Map/Reduce 处理数据的方法。如果您可以避免将整个数据集加载到内存中并在读取时对其进行处理,则可以完全避免所有对象的创建和列表构建。

过去这 30,000,000 的东西是 30,000,000 的东西,如果 您在内存中没有足够的 RAM,它只是要交换 磁盘和磨掉。但是没有足够的信息知道是否 你需要从一个巨大的列表中开始。

【讨论】:

    【解决方案2】:

    感谢您的回答。 Jarrod 关于在 numpy 中使用多维数组的观点是最有帮助的。这是我现在的工作速度快 40 倍的东西:

    parttype = [('ID', int), ('nH', float), ('T', float), ('metallicity', float), ('oxygen', float), ('o6', float), ('o7', float), ('o8', float)]
    
    partlist = np.zeros((npart,), dtype=parttype)
    
    for i in xrange(npart):
        partlist[i] = (int(ID[i]),nH[i],T[i],metallicity[i],oxygen[i],o6[i],o7[i],o8[i])
    

    仍然是一个 for 循环,但对我的数据来说运行速度相当快(6 分钟对 4 小时)!

    【讨论】:

      猜你喜欢
      • 2021-11-25
      • 1970-01-01
      • 2013-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 2021-12-01
      相关资源
      最近更新 更多