在python中创建包含整数的类似列表的对象的最快方法 在python中创建包含整数/浮点数(非常简单的数据类型)的列表状对象的最快方法是什么? 我所说的“类似列表”是什么意思?

在python中创建包含整数的类似列表的对象的最快方法 在python中创建包含整数/浮点数(非常简单的数据类型)的列表状对象的最快方法是什么? 我所说的“类似列表”是什么意思?,python,list,Python,List,这意味着我希望有一个对象支持列表的两个(非常)基本操作:获取某个索引中的对象(1)和更改其值(2) 在发布这篇文章之前,我遇到了哪些帖子,为什么它们没有解决我的问题? 我遇到了这两个: 他们没有解决我的问题,因为他们的所有解决方案都太慢了:在我的电脑中array。array('i',(0,)*10**8)导致了一个错误(lol)[0表示范围内(10**8)]花费了大约15秒(哇!)[0]*10**8耗时2.3秒[无]*10**8耗时1.8秒;(1.8秒可能更快…) 我试着做什么? 我尝试使用c

这意味着我希望有一个对象支持列表的两个(非常)基本操作:获取某个索引中的对象(1)和更改其值(2)

在发布这篇文章之前,我遇到了哪些帖子,为什么它们没有解决我的问题? 我遇到了这两个:

他们没有解决我的问题,因为他们的所有解决方案都太慢了:在我的电脑中
array。array('i',(0,)*10**8)
导致了一个错误(lol)<代码>[0表示范围内(10**8)]花费了大约15秒(哇!)<代码>[0]*10**8耗时2.3秒<代码>[无]*10**8耗时1.8秒;(1.8秒可能更快…)

我试着做什么? 我尝试使用
ctypes
模块

from ctypes import c_int
array = (c_int * 10 ** 8)()
上面的代码只用了0.7秒。。。但是有没有办法让它更快呢?除了速度快之外,它还有一些缺点:

  • 由于它使用c/c++变量的框架,因此其中的整数将处于“不像python那样无限”的整数值范围内
  • 列表中不能有多个数据类型
  • 您必须导入一个模块才能使用它
  • 真的有可能按我的要求去做吗?是否有比使用
    ctypes
    模块更快的方法?如果是,请确保您使用的是“内置”/“预装”模块

    编辑: 为什么我不能简单地安装一些模块,比如numpy? 我使用python进行竞争性编程,大多数解释器/评判员都不允许使用外部库

    我们可以用array.array存储自定义对象吗? 我可以看到许多答案都使用了
    array
    模块的
    array
    功能。它们都使用“i”来指定我们要存储的整数。可以创建一个类并创建一个包含它的“array.array”吗?例如:

    class Point:
     def __init__(self, x, y):
      self.x = x
      self.y = y
    
    # make array.array object with all indexes containing a Point with atributes x and y with value 0
    # an example with a list of what I want to do is this:
    # l = [Point(0, 0) for _ in range(10**3)]
    

    我只想使用
    numpy
    模块,它支持快速数组操作

    例如,制作一个数字为0到10**8的数组:

    import numpy as np
    import time
    
    b = time.time()
    a = np.linspace(0, 10**8, 10**8)
    c = time.time()
    print(c-b)
    >>>0.5000154972076416
    
    或者制作一个长度为10**8的0数组:

    b = time.time()
    a = np.zeros(shape=(10**8,))
    c = time.time()
    print(c-b)
    >>>0.0
    
    numpy之所以这么快,主要是因为它是用C实现的

    编辑: 如果只想使用预装的软件包,可以尝试使用
    array
    软件包:

    import array
    import time
    r = time.time()
    a = array.array('i', [0]) * (10**8)
    print(time.time()-r)
    >>>0.15627217292785645
    

    我想说,你可以尝试不同的方法:

    1)
    numpy
    。它实际上是阵列的标准。每个操作都需要跨越Python C边界,但这实际上取决于您的任务

    x = numpy.array(10 ** 8)
    
    timeit.timeit('x = numpy.array(10 ** 8)', 'import numpy', number=1)
    4.195800283923745e-05
    
    2) 延迟初始化(如JavaScript数组)

    class LazyArray:
    定义初始值(自身,大小):
    self.storage={}
    self.size=大小
    def检查(自我,i):
    如果i<0或i>=self.size:
    引发运行时错误()
    定义获取项目(自我,i):
    自我检查(一)
    返回self.storage.get(i,0)
    定义设置项(自身、i、值):
    自我检查(一)
    自存储[i]=值
    x=LazyArray(10**8)
    x[10]
    >> 0
    x[10]=5
    x[10]
    >> 0
    
    array.array('i',(0,)*10**8)
    导致错误(lol)

    您没有指定您得到了什么错误-这对我来说是有效的,尽管它不是很快,因为它构建了一个中间元组并立即丢弃它。使用Python的内置类型,
    array.array
    可能会获得最佳性能,前提是避免使用元组:

    a = array.array('i', (0,)) * 10**8
    
    上面的代码只用了0.7秒。。。但是有没有办法让它更快呢

    如果不允许创建或导入C扩展名,那么很难击败array.array。在我几年前的机器上,上述操作需要0.6秒。您可以通过增加初始数组的大小来进一步优化它。例如,这会产生相同的结果,但速度几乎快了3倍(!):

    在我的机器上,以下版本效果最佳:

    # 0.19 s
    a = array.array('i', (0,) * 100) * 10**6
    
    进一步增加初始阵列大小没有帮助,很快就会开始降低性能

    <> P>为了获得更好的效率,考虑替代的方法,如懒惰的列表或为您的用例定制的完全不同的数据结构。考虑到竞争的背景,这可能是人们真正寻求的

    但是,请注意,每个解决方案都有不同的权衡。例如,@KonstantinNikitin提供的惰性数组将非常高效地构造,但是它的
    \uuuu getitem\uuuuuuu
    \uuuu setitem\uuuuuu
    在纯Python中实现,将比list或
    array.array
    慢几个数量级。哪一个对您更有利归结为您的程序中哪些操作更频繁,这取决于您自己去发现。

    如果您真的只想要这两个属性:

    获取某个索引中的对象(1)并更改其值(2)

    然后您可以只使用集合。defaultdict:

    import collections
    my_list = collections.defaultdict(lambda: 0)
    
    这相当快(~0.4μs):


    但是,实际使用它可能比其他答案中建议的任何类型都要慢。

    对于只需要0到255之间的整数的情况,
    bytearray
    对象创建速度非常快:

    >>> timeit.timeit('bytearray(100000)', number=1000)
    0.005567271093696036
    >>> timeit.timeit('array.array("B", [0])*100000', 'import array', number=1000)
    0.36631167401839093
    >>> timeit.timeit('array.array("i", [0])*100000', 'import array', number=1000)
    0.56494557472422
    

    array.array
    不同,它直接将分配归零,而不是从用零初始化的对象复制。

    您是否考虑过
    numpy
    ?如果您谈论的是大型数值计算中的性能,那么不必担心导入模块。看你也有
    bytearray(10**8)
    。值的范围是有限的(0-255),但它非常快使用字典可能很慢。。。插入和获取索引操作可能需要O(1),但也可能需要O(n)(最坏情况)是的,延迟初始化有它自己的代价。你可以试着混合。就像手动将间隔拆分为[0..sqrt(size)]dicts列表一样,我没有指定eror,因为当我在我的机器上运行它时
    import collections
    my_list = collections.defaultdict(lambda: 0)
    
    $ python3 -m timeit -s 'import collections' 'collections.defaultdict(lambda: 0)' 
    1000000 loops, best of 3: 0.417 usec per loop
    
    >>> timeit.timeit('bytearray(100000)', number=1000)
    0.005567271093696036
    >>> timeit.timeit('array.array("B", [0])*100000', 'import array', number=1000)
    0.36631167401839093
    >>> timeit.timeit('array.array("i", [0])*100000', 'import array', number=1000)
    0.56494557472422